🚨

Railsで例外をHTTPステータスコードにマッピングする方法

に公開

Railsアプリケーションで例外(エラー)が発生したときに、どのHTTPステータスコードを返すかを指定する方法を順を追って説明します。

はじめに

Railsで例外をHTTPステータスコードにマッピングする方法は複数あります:

  1. ApplicationControllerでrescue_fromを使う方法
  2. カスタム例外ハンドラーを作成する方法
  3. config/application.rbで設定する方法
  4. ActionDispatch::ExceptionWrapper.rescue_responsesを使う方法

それぞれにメリット・デメリットがありますが、今回紹介する ActionDispatch::ExceptionWrapper.rescue_responses を使った方法が最もシンプルで実装しやすいと思います。アプリケーション全体で一括設定でき、コードもわずか数行で済みます。

🔹 全体像

ActiveSupport.on_load(:action_controller) do
  ActionDispatch::ExceptionWrapper.rescue_responses.merge!(
    "ActiveHash::RecordNotFound" => :not_found,
    "Pagy::OverflowError" => :not_found
  )
end

このコードの目的は、特定の例外が発生した際に HTTP ステータスコード 404(:not_found)を返すように Rails に指示することです。

各要素の意味

✅ ActiveSupport.on_load(:action_controller)

これは Railsのフック です。

  • ActionController(Railsのコントローラー機能)が読み込まれたときに、ブロック内の処理を実行します
  • gemなどで定義する際に便利なパターンで、本体よりも後に読み込まれるようなモジュールでも、このブロック内で処理を追記できます

✅ ActionDispatch::ExceptionWrapper.rescue_responses

これは、例外クラス名とHTTPステータスコードのマッピングです。

  • たとえば "ActiveRecord::RecordNotFound" が発生すると、通常は 404(Not Found)を返します

✅ merge!

この Hash に新しい例外マッピングを追加しています。

今回は下記の2つを追加しています:

"ActiveHash::RecordNotFound" => :not_found
"Pagy::OverflowError"        => :not_found

各エラーの意味

🔸 ActiveHash::RecordNotFound

  • ActiveHash は、DBを使わずにモデルのように扱えるGem
  • 存在しないIDなどを検索したときにこのエラーが発生します
  • これを 404 として扱うことで、一般的な「見つかりません」扱いになります

🔸 Pagy::OverflowError

  • Pagy は軽量なページネーションGem
  • ページ番号が存在しない(例:最大5ページなのに ?page=10)とこの例外が発生
  • これも「そのページは存在しない」という意味で 404 にするのが自然です

✅ なぜ必要か

Rails標準ではこれらのエラーは 500 Internal Server Error 扱いになる可能性があります。でも実際はクライアント側のミス(存在しないIDやページ指定)なので、404 Not Found として返す方が適切

📁 実際の実装場所

このコードは、Railsアプリケーションの イニシャライザー に配置します:

config/initializers/exception_mapping.rb

このファイルを作成し、上記のコードを記述することで、アプリケーション起動時に例外マッピングが設定されます。

🔚 まとめ

例外クラス 返すステータス 意味
ActiveHash::RecordNotFound :not_found 指定されたIDのレコードが無い
Pagy::OverflowError :not_found 存在しないページを指定した

Railsが自動的にこのマッピングを見て、エラーハンドリングしてくれるようになります。これでユーザーにとっても自然な挙動になります。

終わりに

そもそもエラーページは、通常のユーザーが目にするものではありません。ですので、無理にカスタマイズしたり、特別にレイアウトを指定したりする必要はないと考えています。

もちろん、URLに応じてレコメンドコンテンツを表示したり、上部にランディングページを表示したりといったニーズもあるかもしれませんが、まずはRailsの標準仕様に従って、シンプルに構築するのがおすすめです。

Discussion