ActiveRecord :: RecordNotFound引发404而不是500

Yar*_*rin 3 ruby-on-rails

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

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

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

fiv*_*git 11

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

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

# config/initializers/rescue_responses_overrides.rb
ActionDispatch::ExceptionWrapper.rescue_responses
  .delete('ActiveRecord::RecordNotFound')
Run Code Online (Sandbox Code Playgroud)

现在Rails会在ActiveRecord::RecordNotFound引发时向浏览器发送500状态代码.您还可以在一个步骤中删除所有条目:

ActionDispatch::ExceptionWrapper.rescue_responses.clear
Run Code Online (Sandbox Code Playgroud)

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

pp ActionDispatch::ExceptionWrapper.rescue_responses
Run Code Online (Sandbox Code Playgroud)


Jiř*_*šil 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
Run Code Online (Sandbox Code Playgroud)

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

  • @Yarin嗯,在一个理想的世界中,内部逻辑错误永远不会冒泡到Web层未处理,但我明白你的观点. (2认同)