我试图从ActionController::RoutingError
营救,但我无法让它发挥作用。我尝试了几乎所有我能在网上找到的东西,包括rescue_from ActionController::RoutingError in Rails 4。我有错误控制器和错误页面。我开始工作cancan access denied
和RecordNotFound
,但我可以解决RoutingError
。
对于cancan,我在application_controller.rb
rescue_from CanCan::AccessDenied do
render template: 'errors/error_403', status: 403
end
我的路线中有这个:
match "/404", to: "errors#error_404", via: :all
如果我为RoutingError
做同样的事情,它就不会工作。
我也试过match '*path', :to => "errors#error_404"
但是我得到了错误。
我该如何解决这个问题?
编辑:如果我对RoutingError
执行与拒绝访问相同的操作:
rescue_from ActionController::RoutingError do
render template: 'errors/error_404', status: 404
end
它不会工作。
答案 0 :(得分:26)
当Rails尝试将请求与路由匹配时,会引发ActionController::RoutingError
。这种情况发生在Rails甚至初始化控制器之前 - 因此您的ApplicationController永远不会有机会挽救异常。
相反,Rails默认exceptions_app
开始 - 注意这是一个Rack意义上的应用程序 - 它需要带有请求的ENV哈希并返回响应 - 在这种情况下是静态/public/404.html
文件
您可以做的是让您的Rails应用程序处理动态呈现错误页面:
# config/application.rb
config.exceptions_app = self.routes # a Rack Application
# config/routes.rb
match "/404", :to => "errors#not_found", :via => :all
match "/500", :to => "errors#internal_server_error", :via => :all
然后,您将设置一个特定的控制器来处理错误页面 - 不要在ApplicationController类中执行此操作,因为您要向所有控制器添加not_found
和internal_server_error
方法!
class ErrorsController < ActionController::Base
protect_from_forgery with: :null_session
def not_found
render(status: 404)
end
def internal_server_error
render(status: 500)
end
end
从Matt Brictson: Dynamic Rails Error Pages借来的代码 - 阅读完整的纲要。
答案 1 :(得分:0)
有一种更好的方法:
routes.rb
Rails.application.routes.draw do
match '*unmatched', to: 'application#route_not_found', via: :all
end
application_controller.rb
class ApplicationController < ActionController::Base
def route_not_found
render file: Rails.public_path.join('404.html'), status: :not_found, layout: false
end
end
要在本地进行测试,请设置以下内容并重新启动服务器。
config / development.rb
config.consider_all_requests_local = false
经过Rails 6的测试。