我想在Rails 3中捕获未知的操作错误,该错误显示开发时的“未知操作”错误以及生产中的404.html。我尝试将这个rescue_from
处理程序放在我的ApplicationController上(以及实际的控制器,以防万一),但我仍然看到了丑陋的错误。
我在404上有自定义内容,它不能是普通的.html文件。
我的路线:
match '/user/:id/:action', controller: 'users'
我正在访问的网址:/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):
还试过rescue_from ActionController::UnknownAction
。
有什么建议吗? 谢谢!
答案 0 :(得分:14)
rescue_from ActionController::RoutingError
了。请参阅here。
目前,解决方案是hamiltop推荐的解决方案。使用捕获到“路由错误”路由的所有路由。确保将它放在config \ routes.rb文件的末尾,以便最后处理。
# Any routes that aren't defined above here go to the 404
match "*a", :to => "application#routing_error"
def routing_error
render "404", :status => 404
end
注意:此方法有一个主要缺点。如果你使用像Jammit或Devise这样的引擎,那么所有路由都将使Rails忽略引擎的路由。
如果您没有使用拥有自己路线的引擎,那么您应该没问题。 但是,如果您使用定义其自己路线的引擎,请参阅@ arikfr的答案。
答案 1 :(得分:9)
使用catch all路径来处理404错误(正如@Seth Jackson建议的那样)有一个主要缺点:如果你使用任何定义自己路由的Rails引擎(例如Jammit),它们的路由将被忽略。
更好,更兼容的解决方案是使用可以捕获404错误的Rack中间件。在我的一个项目中,我实现了将这些错误报告给Hoptoad的Rack中间件。我的实现基于这个:https://github.com/vidibus/vidibus-routing_error,但是我没有再次调用我的Rails应用来处理404错误,而是在Rack中间件中执行它,让nginx显示404页面。
答案 2 :(得分:2)
如果您真的想在控制器中解救AbstractController::ActionNotFound
,可以尝试这样的事情:
class UsersController < ApplicationController
private
def process(action, *args)
super
rescue AbstractController::ActionNotFound
respond_to do |format|
format.html { render :404, status: :not_found }
format.all { render nothing: true, status: :not_found }
end
end
public
# actions must not be private
end
这会覆盖引发process
的{{1}} AbstractController::Base
方法(请参阅source)。
答案 3 :(得分:0)
你有没有试过捕获所有路线?
http://railscasts.com/episodes/46-catch-all-route
您当前使用的通配符路由是一个坏主意(tm)。
我建议定义你关心的路由,然后做一个catchchall作为routes.rb的最后一行(在routes.rb中首先定义的路由以后定义)。然后你可以渲染你想要的任何页面(并指定404状态代码)。
编辑:如果你真的想使用你当前的方法......(虽然这似乎可以被弃用)
def rescue_action(例外) 案例例外 当ActionNotFound,然后是UnknownAction #在这里处理这些例外 其他 超 结束 端