今更Railsのautoloadingとeager loadingを理解する
https://gyazo.com/3480f4f2b999112fe64982541e0823bf
徳川園
いきなり注意
今回言及しているeager loadingは、ActiveRecordのModel.eager_load(:model)とは全く異なる内容なので気をつけてください。
はじめに
Rails 7.2へのアップグレード時にbin/rails app:updateを実行し、サーバを立ち上げたところZeitwerk::NameErrorが発生しました。これをきっかけに、この問題について調査を始めました。
問題の詳細
エラーの内容は、lib/配下の一部のファイル名とモジュール名(またはクラス名)が一致していないというものでした。
Zeitwerkは、Rails 6.0以降に組み込まれた、アプリケーションで定義されたクラスやモジュールを自動で読み込む仕組みです。Zeitwerkを使用する場合、ファイル構造がRubyのクラス名とモジュールに一致する必要があります。
今回のエラーは、これまで自動読み込みの対象ではなかったlib配下のファイルが、自動読み込みの対象となったことが原因でした。
自動読み込みの種類
Zeitwerkの自動読み込みには二種類あります:
1. autoloading: クラスやモジュールを利用する時に、動的に対象のファイルを読み込む機能。
2. eager loading: アプリケーション起動時に、事前に各ファイルを走査し、クラスやモジュールを読み込む機能。
本番環境ではアプリケーション起動後のパフォーマンスを向上させるためになるべくeager loadingを行うことが推奨されますが、開発環境ではファイルの変更を頻繁に行うため、通常オフにすることが推奨されています。
Railsアップデート時の変更内容
アップデート時にconfig/application.rbに以下の設定が追加されました:
code: (ruby)
この設定はlibディレクトリを自動読み込みのパスに含める場合に使用します。autoload_libというメソッド名ですが、eager loadingも有効になります。
最終的な対応
lib配下をeager loading対象から外すため、この設定を削除しました。
余談: autoloadingだけしたい場合
eager loadingを避けつつautoloadingだけ行いたい場合は、以下のように設定します:
code: (ruby)
参考
詳細はRailsガイドを参照してください
https://ogp-image.deno.dev/svg?url=https://railsguides.jp/autoloading_and_reloading_constants.html#.svg https://railsguides.jp/autoloading_and_reloading_constants.html
※ eager loadingに関しては日本語訳がないのかな…