今更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に関しては日本語訳がないのかな…
https://i.gyazo.com/5fa2dc4032f29bc4910e74668d8beba5.png https://x.com/share?url=https%3A%2F%2Fscrapbox.io%2Fwada-blog%2F%25E4%25BB%258A%25E6%259B%25B4Rails%25E3%2581%25AEautoloading%25E3%2581%25A8eager_loading%25E3%2582%2592%25E7%2590%2586%25E8%25A7%25A3%25E3%2581%2599%25E3%2582%258B&text=%E4%BB%8A%E6%9B%B4Rails%E3%81%AEautoloading%E3%81%A8eager+loading%E3%82%92%E7%90%86%E8%A7%A3%E3%81%99%E3%82%8B