Подавление исключения ActionView :: MissingTemplate для Rails 3.x - PullRequest
11 голосов
/ 10 марта 2012

Начиная с Rails 3.0, время от времени я получал уведомления об исключениях, например:

ActionView::MissingTemplate: Missing template [...] with {:locale=>[:en],
  :formats=>[:text], :handlers=>[:erb, :builder, :haml]}. Searched in: * [...]

Например, произвольный рукописный URL, такой как http://example.com/some/path/robots.txt, вызывает ошибку. Не весело.

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

https://rails.lighthouseapp.com/projects/8994/tickets/6022-content-negotiation-fails-for-some-headers-regression

В этом сообщении предлагается исправление,

http://trevorturk.wordpress.com/2011/12/09/handling-actionviewmissingtemplate-exceptions/

Чтобы использовать это:

respond_to do |format|
  format.js
end

Но мне это не кажется правильным, поскольку меня не интересует перегрузка действия несколькими форматами. В моем приложении есть отдельные URL-адреса для HTML и JSON API, поэтому достаточно простого render.

Должен ли я просто проглотить исключение на rescue_from ActionView::MissingTemplate и вернуть 406 сам?

Есть ли лучший способ справиться с этой ситуацией?

Или я могу спросить так: во-первых, есть ли какая-то реальная полезность для повышения такого рода исключений при производстве?

Ответы [ 6 ]

5 голосов
/ 13 мая 2012

Если вам не нужны отформатированные маршруты, вы можете отключить их с помощью: format => false в спецификации маршрута, например,

get '/products' => 'products#index', :format => false

Это сгенерирует RoutingError, которая преобразуется в 404 Not Found. В качестве альтернативы вы можете ограничить его несколькими предопределенными форматами:

get '/products' => 'products#index', :format => /(?:|html|json)/

Если вы хотите отформатированный URL-адрес, но хотите, чтобы он был ограничен одним форматом, вы можете сделать это:

get '/products.json' => 'products#index', :format => false, :defaults => { :format => 'json' }

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

3 голосов
/ 05 сентября 2015

Лучшее, что сработало для меня, - application_controller.rb:

rescue_from ActionView::MissingTemplate, with: :not_found
2 голосов
/ 16 мая 2014

После некоторого исходного погружения я нашел другой способ. Поместите это в инициализатор.

ActionDispatch::ExceptionWrapper.rescue_responses.merge! 'ActionView::MissingTemplate' => :not_found
1 голос
/ 15 июня 2015

Попробуйте добавить

render nothing: true

в конце вашего метода.

1 голос
/ 02 июня 2013

Если у вас есть ресурс, который будет обслуживаться только в одном формате, и вы хотите игнорировать любой заголовок Accept и просто заставить его всегда выводить формат по умолчанию, вы можете удалить формат из имени файла шаблона. Так, например, если у вас есть:

app/views/some/path/robots.txt.erb

Вы можете изменить его на

app/views/some/path/robots.erb

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

0 голосов
/ 13 мая 2012

Если есть определенные пути, которые периодически вызываются, которые генерируют ошибки - и они являются одним и тем же набором URL, которые вызываются регулярно (т. Е. Robots.txt или что-то еще) - лучшее, что можно сделать, если вы можете, этодля начала исключите их попадание на сервер rails.

Как это сделать, зависит от стека вашего сервера.Один из способов сделать это - заблокировать это непосредственно в RACK перед передачей URL-адреса в рельсы.

Другим способом может быть блокировка в NGINX или Unicorn, в зависимости от того, какой вебСлушатель, который вы используете для своего приложения.

Я бы порекомендовал разобраться в этом, а затем вернуться и опубликовать здесь дополнительный вопрос «Как заблокировать URL с помощью Rack?» (Или Unicorn или Nginx или где бы выдумаю, что имеет смысл заблокировать доступ.

...