ActiveRecord :: RecordNotFound引发404而不是500

时间:2015-01-13 15:11:31

标签: ruby-on-rails

我们有一个基本上在生产中默默失败的操作,因为它引发了ActiveRecord::RecordNotFound错误,Rails将其视为404错误而不是500错误 - 这意味着它不会被我们捕获错误记录器。

我不喜欢Rails将某些错误映射到404s-我认为应由开发人员决定URL是否无效,或者检索记录失败是否是应用程序错误。

我们如何确保将所有Rails错误视为500错误?

2 个答案:

答案 0 :(得分:11)

首先,如果您可以手动通知错误记录器错误,那可能是最好的做法。使Rails返回不同的HTTP状态代码可能会破坏应用程序的其他部分。

但是,如果您绝对必须这样做,则可以通过从救援响应哈希中删除相应的条目来指示Rails不返回404。您可以在初始化程序中执行此操作:

# config/initializers/rescue_responses_overrides.rb
ActionDispatch::ExceptionWrapper.rescue_responses
  .delete('ActiveRecord::RecordNotFound')

现在,只要引发ActiveRecord::RecordNotFound,Rails就会向浏览器发送500状态代码。您也可以一步删除所有条目:

ActionDispatch::ExceptionWrapper.rescue_responses.clear

要查看哪些其他错误Rails返回不同的状态代码,您只需在Rails控制台中打印哈希:

pp ActionDispatch::ExceptionWrapper.rescue_responses

答案 1 :(得分:9)

  

它引发了一个ActiveRecord :: RecordNotFound错误,Rails将其视为404错误而不是500错误

这是正确的做法。想象一下,搜索爬虫会点击您的博客应用并在您不存在的博客帖子上收到错误。如果您返回500,则抓取工具会稍后再次尝试访问该页面。如果您返回404,则抓取工具会识别该页面丢失,并可能会停止尝试。如果服务器以500响应,某些浏览器甚至会显示自定义内置页面。

如果您仍想继续,您可以选择一些选项。您可以在顶级控制器中rescue_from并将响应更改为您想要的任何内容。

class ApplicationController < ActionController::Base
  rescue_from ActiveRecord::RecordNotFound, OtherError do |exception|
    render nothing: true, status: 500 # nothing, redirect or a template
  end
end

另一个选择是使用自定义exceptions_app。它基本上是一个机架应用程序,在发生异常时会被调用,您可以使用请求/响应执行任何操作。您可以查看默认实现(ActionDispatch::PublicExceptions)以获取灵感。