Rails: динамический robots.txt с erb

Я пытаюсь сделать динамический текстовый файл (robots.txt) в моем приложении Rails (3.0.10), но он продолжает отображать его как HTML (говорит консоль).

match 'robots.txt' => 'sites#robots'

Контроллер:

class SitesController < ApplicationController

  respond_to :html, :js, :xml, :css, :txt

  def robots
    @site = Site.find_by_subdomain # blah blah
  end

end

приложение/просмотров/сайты/robots.txt.erb:

Sitemap: <%= @site.url %>/sitemap.xml

Но когда я навещаю http://www.example.com/robots.txt, я получаю пустую страницу/источник, и в журнале говорится:

Started GET "/robots.txt" for 127.0.0.1 at 2011-11-21 11:22:13 -0500
  Processing by SitesController#robots as HTML
  Site Load (0.4ms)  SELECT `sites`.* FROM `sites` WHERE (`sites`.`subdomain` = 'blah') ORDER BY created_at DESC LIMIT 1
Completed 406 Not Acceptable in 828ms

Любая идея, что я делаю неправильно?

Примечание. Я добавил это в config/initializers/mime_types, потому что Rails жаловался на то, что не знал, что такое тип .txt mime:

Mime::Type.register_alias "text/plain", :txt

Примечание 2: я удалил файл robots.txt запаса из общего каталога.

Ответ 1

Я думаю, проблема в том, что если вы определяете respond_to в своем контроллере, вы должны использовать respond_with в действии:

def robots
  @site = Site.find_by_subdomain # blah blah
  respond_with @site
end

Кроме того, попробуйте явно указать файл .erb, который будет отображаться:

def robots
  @site = Site.find_by_subdomain # blah blah
  render 'sites/robots.txt.erb'
  respond_with @site
end

Ответ 2

ПРИМЕЧАНИЕ. Это repost из coderwall.

Прочитав несколько советов fooobar.com/questions/370728/...

Routing

# config/routes.rb
#
# Dynamic robots.txt
get 'robots.:format' => 'robots#index'

Controller

# app/controllers/robots_controller.rb
class RobotsController < ApplicationController
  # No layout
  layout false

  # Render a robots.txt file based on whether the request
  # is performed against a canonical url or not
  # Prevent robots from indexing content served via a CDN twice
  def index
    if canonical_host?
      render 'allow'
    else
      render 'disallow'
    end
  end

  private

  def canonical_host?
    request.host =~ /plugingeek\.com/
  end
end

представления

На основе request.host мы создаем один из двух разных файлов просмотра .text.erb.

Разрешить роботы

# app/views/robots/allow.text.erb # Note the .text extension

# Allow robots to index the entire site except some specified routes
# rendered when site is visited with the default hostname
# http://www.robotstxt.org/

# ALLOW ROBOTS
User-agent: *
Disallow:

Запрет пауков

# app/views/robots/disallow.text.erb # Note the .text extension

# Disallow robots to index any page on the site
# rendered when robot is visiting the site
# via the Cloudfront CDN URL
# to prevent duplicate indexing
# and search results referencing the Cloudfront URL

# DISALLOW ROBOTS
User-agent: *
Disallow: /

функции

Тестирование установки с помощью RSpec и Capybara также можно выполнить довольно легко.

# spec/features/robots_spec.rb
require 'spec_helper'

feature "Robots" do
  context "canonical host" do
    scenario "allow robots to index the site" do
      Capybara.app_host = 'http://www.plugingeek.com'
      visit '/robots.txt'
      Capybara.app_host = nil

      expect(page).to have_content('# ALLOW ROBOTS')
      expect(page).to have_content('User-agent: *')
      expect(page).to have_content('Disallow:')
      expect(page).to have_no_content('Disallow: /')
    end
  end

  context "non-canonical host" do
    scenario "deny robots to index the site" do
      visit '/robots.txt'

      expect(page).to have_content('# DISALLOW ROBOTS')
      expect(page).to have_content('User-agent: *')
      expect(page).to have_content('Disallow: /')
    end
  end
end

# This would be the resulting docs
# Robots
#   canonical host
#      allow robots to index the site
#   non-canonical host
#      deny robots to index the site

В качестве последнего шага вам может потребоваться удалить статический public/robots.txt в общей папке, если он все еще присутствует.

Надеюсь, вы сочтете это полезным. Не стесняйтесь комментировать, помогая еще больше улучшить эту технику.

Ответ 3

Одно решение, которое работает в Rails 3.2.3 (не уверен в 3.0.10), выглядит следующим образом:

1) Назовите файл шаблона robots.text.erb # Акцент на text vs. txt

2) Настройте свой маршрут следующим образом: match '/robots.:format' => 'sites#robots'

3) Оставьте свое действие как есть (вы можете удалить response_with в контроллере)

def robots
  @site = Site.find_by_subdomain # blah blah
end

Это решение также устраняет необходимость явно указывать txt.erb в вызове render, упомянутом в принятом ответе.

Ответ 4

Мне не нравится идея достижения robots.txt моего веб-сервера.

Если вы используете Nginx/Apache в качестве своего обратного прокси, статические файлы будут намного быстрее обрабатывать их, чем запрос, направляющий рельсы.

Это намного чище, и я думаю, что это быстрее.

Попробуйте использовать следующую настройку.

nginx.conf - для производства

location /robots.txt {
            alias /path-to-your-rails-public-directory/production-robots.txt;
    }

nginx.conf - для этапа

location /robots.txt {
                alias /path-to-your-rails-public-directory/stage-robots.txt;
        }

Ответ 5

Для моих проектов с рельсами у меня обычно есть отдельный контроллер для ответа robots.txt

class RobotsController < ApplicationController
  layout nil

  def index
    host = request.host
    if host == 'lawc.at' then #liveserver
      render 'allow.txt', :content_type => "text/plain"
    else #testserver
      render 'disallow.txt', :content_type => "text/plain"
    end
  end

end

Затем у меня есть названия с именем: disallow.txt.erb и allow.txt.erb

И в моем routes.rb у меня есть

get "robots.txt" => 'robots#index'