rescue_from ActionController :: RoutingError不起作用

时间:2016-05-11 21:22:52

标签: ruby-on-rails ruby-on-rails-4

我试图从ActionController::RoutingError营救,但我无法让它发挥作用。我尝试了几乎所有我能在网上找到的东西,包括rescue_from ActionController::RoutingError in Rails 4。我有错误控制器和错误页面。我开始工作cancan access deniedRecordNotFound,但我可以解决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
它不会工作。

2 个答案:

答案 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_foundinternal_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的测试。