Railsのエラーページをカスタマイズする(翻訳)
本記事は、私の著書『The Rails and Hotwire Codex』から抜粋して手を加えたものです。
Railsで何らかの問題が発生したときに表示されるデフォルトのエラーページは、かなり退屈です。
デフォルトのRails 404エラーページ
このエラーページは/public
フォルダ内に保存されていて、Railsスタックによってレンダリングされません。
このエラーページの見た目をもう少し麗しくしたいので、Railsインフラストラクチャを使ってエラーをレンダリングするためのコントローラーを作成することにします。
🔗 セットアップ
例外やスタックトレースの代わりに、一般公開したいエラーをレンダリングするために、Railsのdevelopmentモードでconsider_all_requests_local
設定を以下のように変更する必要があります。
# config/environments/development.rb
require "active_support/core_ext/integer/time"
Rails.application.configure do
# ...
config.consider_all_requests_local = false
end
次に、以下を実行してコントローラを作成します。
$ bin/rails g controller errors --no-helper --no-test-framework
このコントローラにあるのはshow
アクションだけです。このアクションは、発生した例外のエラーコードを抽出し、適切なビューをレンダリングします。エラーコード 403
、404
、500
については専用のエラーページを用意し、それ以外のエラーについて404
ページにフォールバックすることにします。
class ErrorsController < ApplicationController
layout "error"
def show
@exception = request.env["action_dispatch.exception"]
@status_code = @exception.try(:status_code) ||
ActionDispatch::ExceptionWrapper.new(
request.env, @exception
).status_code
render view_for_code(@status_code), status: @status_code
end
private
def view_for_code(code)
supported_error_codes.fetch(code, "404")
end
def supported_error_codes
{
403 => "403",
404 => "404",
500 => "500"
}
end
end
上のコードを見ると、layout "error"
でエラー用のカスタム"error"レイアウトを使っていることもわかります。このカスタムレイアウトでは、通常のアプリケーションレイアウトの要素は不要なので、シンプルなものにします。
以下を実行して新しいエラーレイアウトを作成します。
$ touch app/views/layouts/error.html.erb
<%# app/views/layouts/error.html.erb %>
<!DOCTYPE html>
<html>
<head>
<%= render "layouts/head" %>
</head>
<body>
<main>
<%= yield %>
</main>
</body>
</html>
ビューを作成して、好みのスタイルでエラーページを作成します。
$ touch app/views/errors/403.html.erb
$ touch app/views/errors/404.html.erb
$ touch app/views/errors/500.html.erb
次は、エラー時にこのコントローラが使われるようRailsに指示する必要があります。
🔗 exceptions_app
Railsには、カスタムエラーをレンダリングするためのフックがあり、これはexceptions_app
というプロパティで設定できます。このプロパティには、例外が発生したときに呼び出されるRackアプリを割り当てる必要があります。
Railsのあらゆるコントローラアクションは、実際には独自のRackアプリケーションです。Rackエンドポイントは、コントローラクラスのaction
メソッドによって返されます。
# ...
module MyApp
class Application < Rails::Application
config.load_defaults 7.0
config.exceptions_app = ->(env) {
ErrorsController.action(:show).call(env)
}
end
end
サーバーを再起動して、存在しないページにアクセスしてみましょう(コントローラアクションで手動でエラーをトリガーしても構いません)。カスタムエラーページが実際に表示されることがわかります。
お知らせ
本記事を気に入っていただけたら、ぜひ私の著書『The Rails and Hotwire Codex』を読んでRailsとHotwireのスキルをアップしてください。
概要
原著者の許諾を得て翻訳・公開いたします。