Отсутствует шаблонный блог/индекс в проекте Ruby on Rails

Для одного из моих проектов я получаю это исключение время от времени:

ActionView:: MissingTemplate: Отсутствуют шаблонные блоги/индекс с помощью {: handlers = > [: rxml,: erb,: builder,: rjs,: haml,: rhtml],: formats = > [ "image/jpeg", "image/pjpeg", "image/png", "image/gif" ],: locale = > [: en,: en]} в пути просмотра "/var/www/keeponposting/релизы/20110403083651/app/views"

Кажется, кто-то запрашивает изображение с URL-адреса, который не является изображением:

HTTP_ACCEPT "image/jpeg, image/pjpeg, image/png, image/gif"

Любые идеи, что с этим делать? Должен ли я реализовать обработчик для одного из них и вернуть "", чтобы избавиться от этих исключений, или есть лучший способ справиться с этим?

Теперь я получаю следующее:

ActionView:: MissingTemplate: Отсутствует шаблонный блог/индекс с помощью {: formats = > [ "text/*" ],: handlers = > [: rjs,: haml,: rhtml,: erb,: rxml,: builder],: locale = > [: en,: en]} в пути просмотра "/var/www/keeponposting/релизы/20110415040109/app/views"

Нет ли способа отправить обратно HTML независимо от формата запроса?

Ответы

Ответ 1

Я исправил эту проблему (несколько минут назад - пока что так хорошо) с этой новой версией Rails 3.1:

config.action_dispatch.ignore_accept_header = true

Как упоминалось в этой проблеме Rails. Это находится в config/application.rb.

Я протестировал его так же, как в RSpec-запросе (используя Capybara):

it "should not break with HTTP_ACCEPT image/*;w=320;h=420 from iPhone" do
  page.driver.header "Accept", "image/*;w=320;h=420"
  visit "/some/path"
  page.should have_content("Some content")
end

Ответ 2

Я соглашаюсь на блокировку робота-нарушителя, но если вы действительно хотите заставить формат ответа добавить before_filter и установить request.format = :html, вот так:

before_filter :force_request_format_to_html

private

def force_request_format_to_html
  request.format = :html
end

Ответ 3

Вот более строгий ответ; предложение purp, из обсуждения issue 4127.

class FooController
  rescue_from  ActionView::MissingTemplate, :with => :missing_template

  def missing_template
    render :nothing => true, :status => 406
  end
end

Ответ 4

У меня возникло бы желание спасти MissingTemplate в вашем контроллере приложений и записать заголовок Referrer, чтобы узнать, что вызывает этот запрос. Вы никогда не знаете, это может быть какая-то неясная часть вашего собственного приложения!

Если, с другой стороны, вы уверены, что это вызвано роботом, рассмотрели ли вы возможность добавить URL-адрес нарушения в файл robots.txt? Например:

User-Agent: YandexImages
Disallow: /your/failed/path

Замена 'your/failed/path' с помощью пути, которым робот спотыкается. Если робот борется повсюду, вы можете просто запретить доступ ко всему сайту для этого конкретного робота:

User-Agent: YandexImages
Disallow: /

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

Ответ 5

Я сделал это: В моем контроллере я поставил фильтр перед:

def acceptable_mime_type
  unless request.accepts.detect{|a| a == :json || a == :html} || request.accepts.include?(nil)
    if request.accepts.detect{|a| a.to_s().include?("*/*")}
      ActionDispatch::Request.ignore_accept_header = true
    else
      render text: "Unacceptable", status: 406
      false
    end
  end
end

Он проверяет мои поддерживаемые типы (например, json, html) и nil (nil отображает по умолчанию html), а затем, если эти типы mime не поддерживаются, он проверяет "/" в заголовке. Если он найдет это, я заставляю рельсы отображать тип mime по умолчанию, игнорируя заголовок accept.

Чтобы проверить это в rspec, я должен был сделать это:

describe 'bad header' do
  describe 'accept' do
    let(:mimeTypes) { ["application/text, application/octet-stream"] }

    it 'should return a 406 status code' do
      request.accept = mimeTypes
      get 'index'
      expect(response.response_code).to eq 406
    end

    describe 'with */* included' do
      it 'should return a 200 status code' do
        request.accept = ["*/*"] + mimeTypes
        get 'index'
        expect(response.response_code).to eq 200
      end
    end
  end
end

По какой-то причине у меня возникали проблемы с попыткой отправить соответствующие заголовки в rspec, используя описанные здесь методы , но я обнаружил, что задал запрос. Массив, оба моих теста прошли. Странно, я знаю, но сейчас я перехожу к следующей проблеме.

Ответ 6

Добавить formats: [:html] для рендеринга:

def action
  render formats: [:html]
end