コード日進月歩

しんくうの技術的な小話、メモ、つれづれ、など

Railsで最上位までExceptionが抜けた場合にRails側でハンドリングしてくれるエラーを追加したい場合はconfigに設定を追記する

ActiveRecord::RecordNotFoundをraiseしたときに404になるときに静的な404ページ出しているのでそれをそのまま真似て他のエラーでもキャッチしてくれないかな」という悩みを持つ人向け

検証したバージョン

$ bin/rails -v
Rails 7.0.6

前提としての動きのメカニズム

  • ActionDispatch::ExceptionWrapper.rescue_responsesにExceptionと対応するエラーのシンボルがある
  • Rack::Utils.status_codeを使ってシンボルを数値に変換
  • 変換した値を使って /public/{{ステータスコード数値}}.html あるいは /public/{{ステータスコード数値}}.{{i18nのロケール文字列}}.html の静的ファイルを読み取り表示。

詳しい挙動をトレースしたものは以下の記事に順を追って説明されているので参照のこと。

Railsのミドルウェアのエラーハンドリング

独自のエラーでも表示をしてもらうには

たとえば以下のようなエラークラスを作って、このエラーをキャッチした場合は404を出したいとする。

module OriginalException
  class HyperAccident < StandardError

  end
end

その場合は環境ごとのconfigに当該エラーをキャッチした場合の設定を追記してあげる。

Rails.application.configure do
  ### 中略 ###
  config.action_dispatch.rescue_responses = {
    # keyは対象となるException、valueに設定するのはHTTPステータスコードのシンボル。
    "OriginalException::HyperAccident" => :not_found
  }
end

上記のように記載してあげれば、404と同じ静的なHTMLを表示してくれる。例えば以下の場合 /test/0 でアクセスするとpublic配下に配置した404.htmlを表示する

class TestController < ApplicationController
  def show
    raise ::OriginalException::HyperAccident if params[:id] == "0"
    render json: {test: params}
  end
end

独自のviewや処理を加えたい場合は rescue_from を活用したほうがいいがそちらは関連リンク参照のこと。

関連リンク