抑制Rails 3.x的ActionView :: MissingTemplate异常

时间:2012-03-10 02:49:12

标签: ruby-on-rails templates exception

从Rails 3.0开始,我不时会收到这样的异常通知:

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

例如,像http://example.com/some/path/robots.txt这样的任意手写URL会引发错误。不好玩。

我很久以前在这张票中报告了这个问题,并且一直在使用这里提到的补丁,但问题仍然存在。

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

但是我感觉不对,因为我对使用多种格式重载动作不感兴趣。在我的应用中,HTML和JSON API有单独的URL,因此简单render就足够了。

我应该通过rescue_from ActionView::MissingTemplate吞下异常并自己返回406吗?

有没有更好的方法来处理这种情况?

或者我可以这样问 - 首先,在生产中提出这种例外是否有任何实际用处?

6 个答案:

答案 0 :(得分:5)

如果您不需要格式化路线,可以使用以下方法停用它们:format =>您的路线规范中为false,例如

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

这将生成一个RoutingError,它将转换为404 Not Found。或者,您可以将其限制为多种预定义格式:

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

如果您想要一个格式化的网址,但希望它仅限于一种格式,那么您可以这样做:

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

在生产中引发此错误有很多正当理由 - 例如,部署中丢失的文件,或者您可能希望通知某人试图破解您的应用程序的网址。

答案 1 :(得分:3)

最适合我的是application_controller.rb

rescue_from ActionView::MissingTemplate, with: :not_found

答案 2 :(得分:2)

在一些潜水源潜水后,我发现了另一种方式。把它放在初始化器中。

ActionDispatch::ExceptionWrapper.rescue_responses.merge! 'ActionView::MissingTemplate' => :not_found

答案 3 :(得分:1)

如果您的资源只能以一种格式提供,并且您希望忽略任何Accept标头并只是强制它始终输出默认格式,则可以从模板文件名中删除该格式。例如,如果你有:

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

您可以将其更改为

app/views/some/path/robots.erb

有些学派会说这是一件坏事,因为你以不同的格式返回数据,但实际上有很多行为不端的用户代理,并非每个网站都仔细过滤内容类型请求,持续回归同样的事情是可预测的行为,所以我认为这是一种合理的方式。

答案 4 :(得分:1)

尝试添加

template <typename Key, typename T>
void searchInMapByKey(std::map<Key,T> Map, Key keyValue)

在方法结束时。

答案 5 :(得分:0)

如果有定期调用的特定路径会产生错误 - 并且它们是定期调用的相同网址集(即robots.txt或其他) - 如果可以,最好的办法是消除他们开始使用rails服务器。

如何执行此操作取决于您的服务器堆栈。一种方法是在将url传入rails之前直接在RACK中阻止它。

另一种方法可能是在NGINX或Unicorn中阻止它,具体取决于您为应用使用的网络侦听器。

我建议调查一下,然后回来并在“如何使用Rack阻止URL?”(或者unicorn或nginx或者您认为阻止访问的任何地方)中发布另一个问题。