Rails5でenable_dependency_loading = trueするのはどうなのか
Ruby on Rails5では,production環境でのautoloadが廃止されました.
Upgrading Ruby on Rails — Ruby on Rails Guides
Rails5では,その代わりにeager_loadを行なっていて,これはデフォルトでは,autoload_pathsにデフォルトで指定されているファイルと同じファイルをアプリケーション起動時に全て読み込んでおくということになっています.
よく lib 以下を config.autoload_paths << Rails.root.join("lib") といった風に追加しているのを見かけるし,実際に自分もやっています.
ここで問題になるのが, autoload_paths に lib 以下を追加しているので,もちろんproduction環境時にlib以下が読み込まれなくなってしまうということです.
ここでさっきのGuideを読むと,
For the vast majority of applications this change needs no action. But in the very rare event that your application needs autoloading while running in production mode, set Rails.application.config.enable_dependency_loading to true.
「圧倒的大部分のアプリケーションは何もする必要がない.puroduction環境で実行中にautoloadingする必要のあるとてもめずらしいアプリケーションの場合は, Rails.application.config.enable_dependency_loading = true にしてください」と書かれています.
じゃあRails.application.config.enable_dependency_loading = trueすれば良いんだ,ということではないです.
圧倒的大部分のアプリケーションでは何もする必要がなく,trueにするのはメチャクチャまれだとかなり強調して言っています.ここは,ちょっと調べないといけないなと思うわけなんですが,面白いissueがあります.
色々議論されているんですが,eager_loadの場合も,autoloadingしていてスレッドセーフじゃないということなんですが,スレッドセーフの問題があったようです….
If developers follow our guidelines of not changing autoload_paths, adding directories to app for autoloading code and explicitly requiring code in lib then Rails will be threadsafe.
threadsafeにするには,私たちのガイドライン(非公式)に従ってautoload_pathsを変更せずに,明示的にrequireすると良いとかかれています.
とにかくautoloadするのはスレッドセーフの観点から良くないということがわかります.
なので解決策としては,
1. app以下にlibを持っていく
読み込まれる必要のあるコードをapp以下にlibディレクトリなどを作って,置いておく
2. とにかくrequireする
3. lib以下をeager_load_pathsに追加する
autoload_paths同様にeager_load_pathsが指定できるので,ここで lib以下を指定する方法ですが,Rakeタスクなどあると思うので良くない
4. 必要なファイルを適宜requireするか、eager_load_pathsに追加する
まあ良い
あたりがあるのではないかと思われます.
自分も知らねーという感じだったし,こういったことは公式でドキュメントにすべきだというissueが立つも完全スルーのまま終わったり,
Upgrading guideもスレッドセーフなどには触れずにかなり曖昧な説明にしているあたりに特別な何かを感じるのだが,これは一体