autoload_paths and eager_load_paths in Rails
autoload
ある定数がコード中に出現した時点で未定義だったとき、特定のディレクトリ内のファイルを探索・評価する仕組み
RubyデフォルトのNameError (uninitialized constant Foo) を発生させる前に探索が行われる
見つからなかった場合はNameErrorがraiseされる
Rubyで require 'foo' したときに $LOAD_PATH から foo.(rb|so|o|dll) etc. を探索するのと同じように、Railsでは autoload_paths から探索をする
autoload_pathsはデフォルトで以下の設定
起動時にアプリケーションやエンジンのappディレクトリ以下に存在するすべてのサブディレクトリ(app/controllersなど)
app以下にapp/workersなどの独自のディレクトリを足してもautoload_pathsに自動的に属する
アプリケーションやエンジンのすべてのapp/*/concerns
test/mailers/previews
Rails5からの変化
production環境ではautoloadは行われないようになった
スレッドセーフでない可能性がある
productionでは後述のeager_loadを利用する
config.paths.add 'lib', eager_load: true
eager_loadとは
アプリケーションの起動時に特定のディレクトリに存在するファイルをロードしておく仕組み
起動時間は増すがスレッド安全性の向上や読み込み順序によるバグを防げる
ロード対象のディレクトリはeager_load_pathsに設定する
デフォルトではautoload_pathsと同じ設定になっている
各環境ごとの違い
production
起動速度よりも安全性を重視する
起動時(つまりアプリケーションがリクエストを受け付け可能になるまでの間)にeager_load_pathsにあるファイルをすべて読み込み、その後自動読み込みをオフにする
eager loading中には自動読み込みがオンであることに注意。eager loadするために必要になることがあるため
autoload: false
eager_load: true
development / test
起動・実行速度を優先する
autoload: true
eager_load: false
設定
いずれも congid/application.rbで設定可能
環境個別の設定を行うことはできない(混乱を引き起こさないためか)
なるべくなら変更しない方が望ましい
It is possible to add new locations to both config.eager_load_paths and config.autoload_paths but use at your own risk.
基本的にRailsでの開発をしていてrequire , require_relativeなどが必要になるケースはほぼない
もし require を書くかautoload_pathsをいじるかしないと動かない場合、Rails wayを外れていると思ったほうが良い
また、autoload_pathsの探索範囲を広げるとファイル探索が遅い環境(Docker for macとか)での開発やテストが遅くなる可能性がある
読み込み順に依存する問題が生じた結果、spring gemが使えなくなることがある 順序依存で壊れたプロセスをforkしても壊れたままなのでspring止めてやりなおし
Zeitwork