在 Rails 3 中捕获自定义 404 的未知操作
我想捕获 Rails 3 中的未知操作错误,该错误在开发中显示“未知操作”错误,在生产中显示 404.html。我尝试将这个 rescue_from 处理程序放在我的 ApplicationController 上(也放在实际的控制器上,以防万一),但我仍然看到了丑陋的错误。
我在 404 上有自定义内容,它不能是纯 .html 文件。
我的路线:
match '/user/:id/:action', controller: 'users'
我正在访问的 URL: /user/elado/xxx
rescue_from
代码:
rescue_from AbstractController::ActionNotFound, :with => :action_not_found
def action_not_found
render text: "action_not_found"
end
浏览器中的错误:
Unknown action
The action 'xxx' could not be found for UsersController
在控制台中:
Started GET "/user/elado/xxx" for 127.0.0.1 at 2011-09-07 19:16:27 -0700
AbstractController::ActionNotFound (The action 'xxx' could not be found for UsersController):
也尝试过 save_from ActionController::UnknownAction
。
有什么建议吗? 谢谢!
I want to catch unknown action error in Rails 3, that shows "Unknown Action" error on development and the 404.html on production. I tried putting this rescue_from
handler on my ApplicationController (and also on an actual controller, just in case) but I still see the ugly error.
I have custom stuff on the 404, and it can't be plain .html file.
My route:
match '/user/:id/:action', controller: 'users'
The URL I'm accessing: /user/elado/xxx
The rescue_from
code:
rescue_from AbstractController::ActionNotFound, :with => :action_not_found
def action_not_found
render text: "action_not_found"
end
The error in the browser:
Unknown action
The action 'xxx' could not be found for UsersController
And in the console:
Started GET "/user/elado/xxx" for 127.0.0.1 at 2011-09-07 19:16:27 -0700
AbstractController::ActionNotFound (The action 'xxx' could not be found for UsersController):
Tried also rescue_from ActionController::UnknownAction
.
Any suggestions?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
当 Rails 3 发布时,rescue_from 略有问题(在 3.1 中也仍然有问题)。基本上你不能:
不再了。请参阅此处。
目前的解决方案是 Hamilton 推荐的。使用通向“路由错误”路由的全部路由。确保将其放在 config\routes.rb 文件的末尾,以便最后处理它。
注意:此方法有一个主要缺点。如果您使用 Jammit 或 Devise 等引擎,则 catch all 路由将使 Rails 忽略引擎的路由。
如果您没有使用有自己的路线的引擎,那么您应该没问题。
但是,如果您确实使用定义自己的路由的引擎,请参阅@arikfr 的答案。
rescue_from was slightly broken when Rails 3 came out (still broken in 3.1 too). Basically you can't:
anymore. See here.
The solution, for now, is what hamiltop recommends. Use a catch all route that goes to your "routing error" route. Make sure you put it at the end of your config\routes.rb file so it is processed last.
Note: This method has one major drawback. If you use an engine such as Jammit or Devise the catch all will route will make Rails ignore the engine's routes.
If you aren't using an engine that has it's own routes then you should be fine.
However, if you do use an engine that defines its own routes see @arikfr's answer.
使用捕获所有路由来处理 404 错误(如 @Seth Jackson 建议的那样)有一个主要缺点:如果您使用任何定义自己的路由的 Rails 引擎(例如 Jammit),它们的路由将被忽略。
更好、更合规的解决方案是使用能够捕获 404 错误的 Rack 中间件。在我的一个项目中,我实现了这样的 Rack 中间件,将这些错误报告给 Hoptoad。我的实现基于此:https://github.com/vidibus/vidibus-routing_error,但是再次调用我的 Rails 应用程序来处理 404 错误,我在 Rack 中间件中执行此操作,并让 nginx 显示 404 页面。
Using a catch all route to handle 404 erros (as @Seth Jackson suggested) has one major drawback: if you use any Rails engines that define their own routes (such as Jammit) their routes will be ignored.
Better and more compliant solution would be to use a Rack middleware that will catch 404 errors. In one of my projects, I've implemented such Rack middleware that reports these errors to Hoptoad. I've based my implementation on this one: https://github.com/vidibus/vidibus-routing_error, but instead of invoking my Rails app again to handle the 404 error, I do it in the Rack middleware and let nginx to show the 404 page.
如果你真的想拯救控制器中的
AbstractController::ActionNotFound
,你可以尝试这样的方法:这会覆盖
AbstractController::Base
的process
方法code> 引发AbstractController::ActionNotFound
(参见 来源)。If you really want to rescue
AbstractController::ActionNotFound
in a controller, you can try something like this:This overrides the
process
method ofAbstractController::Base
that raisesAbstractController::ActionNotFound
(see source).您尝试过catch all 路线吗?
http://railscasts.com/episodes/46-catch-all-route
您当前使用的通配符路线是一个坏主意。
我建议定义您关心的路由,然后将其作为routes.rb 的最后一行(首先在routes.rb 中定义的路由胜过后面的定义)。然后您可以呈现您想要的任何页面(并指定 404 状态代码)。
编辑:如果你真的想使用当前的方法...(尽管这看起来可能会被弃用)
def rescue_action(exception)
例外情况
当 ActionNotFound 时,UnknownAction 然后
# 在这里处理这些异常
别的
极好的
结尾
结尾
Have you tried a catch all route?
http://railscasts.com/episodes/46-catch-all-route
The wildcard route that you are current using is a Bad Idea(tm).
I would recommend defining the routes you care about, and then doing a catchall as the last line of routes.rb (routes defined first in routes.rb trump later definitions). Then you can render whatever page you want (and specify the 404 status code).
Edit: If you really want to use your current approach... (although this seems like it could be deprecated)
def rescue_action(exception)
case exception
when ActionNotFound, UnknownAction then
# Handle these exceptions here
else
super
end
end