在 Rails 4 中救援来自 ActionController::RoutingError

Posted

技术标签:

【中文标题】在 Rails 4 中救援来自 ActionController::RoutingError【英文标题】:rescue_from ActionController::RoutingError in Rails 4 【发布时间】:2014-11-08 14:03:51 【问题描述】:

我遇到以下错误:

ActionController::RoutingError (No route matches [GET] "/images/favicon.ico")

我想为不存在的链接显示 error404 页面。

我怎样才能做到这一点?

【问题讨论】:

【参考方案1】:

app/assets/images 中复制 favicon 图片 对我有用。

【讨论】:

【参考方案2】:

application_controller.rb 中添加以下内容:

  # You want to get exceptions in development, but not in production.
  unless Rails.application.config.consider_all_requests_local
    rescue_from ActionController::RoutingError, with: ->  render_404  
  end

  def render_404
    respond_to do |format|
      format.html  render template: 'errors/not_found', status: 404 
      format.all  render nothing: true, status: 404 
    end
  end

我通常也会挽救以下异常,但这取决于你:

rescue_from ActionController::UnknownController, with: ->  render_404  
rescue_from ActiveRecord::RecordNotFound,        with: ->  render_404  

创建错误控制器:

class ErrorsController < ApplicationController
  def error_404
    render 'errors/not_found'
  end
end

然后在routes.rb

  unless Rails.application.config.consider_all_requests_local
    # having created corresponding controller and action
    get '*path', to: 'errors#error_404', via: :all
  end

最后一件事是在/views/errors/ 下创建not_found.html.haml(或您使用的任何模板引擎):

  %span 404
  %br
  Page Not Found

【讨论】:

这在 Rails 4.2.5 中不起作用。我猜这是因为 ActionDispatch 在运行任何控制器代码之前引发了异常。 @depquid 我是在 Rails 4.0.x 时代写的,但刚刚用 Rails 4.2.5 测试过——我想你没有添加路由也没有创建errors_controller.rb :)如果是这种情况 - 请务必收回反对票,除非您有更多理由放弃它 抱歉,我没有正确设置路由。但是,如果您直接路由到操作,为什么还要 rescue_from ActionController::RoutingError, with: -&gt; render_404 如果您需要在运行任何控制器代码之前(即在路由级别)捕获此问题,请参阅下面的@misu 答案以添加match '*path' =&gt; 'errors#error_404', via: :all 当您的路径匹配所有内容 (get '*path', to: 'errors#error_404', via: :all) 时,您如何获得 ActionController::RoutingError【参考方案3】:

@Andrey Deineko,您的解决方案似乎仅适用于在 conrtoller 内手动引发的 RoutingErrors。如果我尝试使用 url my_app/not_existing_path,我仍然会收到标准错误消息。

我猜这是因为应用程序甚至没有到达控制器,因为 Rails 之前引发了错误。

为我解决问题的trick 是在路由的end 处添加以下行:

Rails.application.routes.draw do
  # existing paths
  match '*path' => 'errors#error_404', via: :all
end

捕获所有未预定义的请求。

然后在ErrorsController中你可以使用respond_to来服务html、json...请求:

class ErrorsController < ApplicationController
  def error_404
    @requested_path = request.path
    repond_to do |format|
      format.html
      format.json  render json: routing_error: @requested_path 
    end
  end
end

【讨论】:

你能解释一下@requested_path = request.path及其对应的调用format.json render json: routing_error: @requested_path 吗? 我刚刚在模板中使用了@requested_path (error_404.html.haml)。至于 json,如果我确定我不希望返回完整页面,例如通过 ajax,我可以要求返回 json,并得到错误消息 @misu 这很完美,你在config/routes.rb 文件中添加它的技巧是关键

以上是关于在 Rails 4 中救援来自 ActionController::RoutingError的主要内容,如果未能解决你的问题,请参考以下文章

Rails:救援类继承

关系数据库在视图中显示来自不同表的字段,rails

开始和救援块异常处理

尝试通过弹性 beantalk 运行救援时忽略 .ebextensions 文件

在 Rails 4 中自动加载 lib 文件

在 Rails 4 生产环境中找不到资产的 404 错误