简体   繁体   English

rescue_from ActionController::RoutingError 不起作用

[英]rescue_from ActionController::RoutingError doesn't work

I'm trying to rescue from ActionController::RoutingError and I can't get it to work.我正在尝试从ActionController::RoutingError拯救出来,但我无法让它工作。 I tried almost everything that I could find online, including rescue_from ActionController::RoutingError in Rails 4 .我尝试了几乎所有可以在网上找到的内容,包括Rails 4 中的 rescue_from ActionController::RoutingError I have an errors controller and error pages.我有一个错误控制器和错误页面。 I got to work cancan access denied and RecordNotFound , but I can solve the RoutingError .我开始工作 cancan access deniedRecordNotFound ,但我可以解决RoutingError

For cancan I use this inside application_controller.rb对于 cancan 我在application_controller.rb使用它

rescue_from CanCan::AccessDenied do
    render template: 'errors/error_403', status: 403
  end

and I have this in my routes:我的路线中有这个:

match "/404", to: "errors#error_404", via: :all

If I do the same thing for RoutingError it won't work.如果我对RoutingError做同样的事情,它将不起作用。

I've also tried match '*path', :to => "errors#error_404" but I get erors.我也试过match '*path', :to => "errors#error_404"但我得到了错误。

How can I solve this?我该如何解决这个问题?

Edit: If I do the same thing for RoutingError as for access denied:编辑:如果我对RoutingError与拒绝访问相同的RoutingError

    rescue_from ActionController::RoutingError do
       render template: 'errors/error_404', status: 404
    end

it won't work.它不会工作。

The ActionController::RoutingError is raised when Rails tries to match the request with a route.当 Rails 尝试将请求与路由匹配时,会引发ActionController::RoutingError This happens before Rails even initializes a controller - thus your ApplicationController never has a chance to rescue the exception.这发生在 Rails 甚至初始化控制器之前 - 因此您的 ApplicationController 永远没有机会挽救异常。

Instead the Rails default exceptions_app kicks in - note that this is an app in the Rack sense - it takes a ENV hash with a request and returns a response - in this case the static /public/404.html file.相反,Rails 默认的exceptions_app启动——请注意,这是一个 Rack 意义上的应用——它接受一个带有请求的 ENV 哈希并返回一个响应——在这种情况下是静态的/public/404.html文件。

What you can do is have your Rails app handle rendering the error pages dynamically instead:您可以做的是让您的 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

You would then setup a specific controller to handle the error pages - don't do this in your ApplicationController class as you would be adding a not_found and internal_server_error method to all your controllers!然后您将设置一个特定的控制器来处理错误页面 - 不要在您的 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

Code borrowed from Matt Brictson: Dynamic Rails Error Pages - read it for the full rundown.Matt Brictson借来的代码:Dynamic Rails Error Pages - 阅读全文。

There is a better way to do it:有一个更好的方法来做到这一点:

routes.rb路由文件

Rails.application.routes.draw do
  match '*unmatched', to: 'application#route_not_found', via: :all
end

application_controller.rb应用控制器.rb

class ApplicationController < ActionController::Base
  def route_not_found
    render file: Rails.public_path.join('404.html'), status: :not_found, layout: false
  end
end

To test locally, set the following and restart server.要在本地进行测试,请设置以下内容并重新启动服务器。

config/development.rb配置/开发.rb

config.consider_all_requests_local = false

Tested with Rails 6.用 Rails 6 测试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM