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もスレッドセーフなどには触れずにかなり曖昧な説明にしているあたりに特別な何かを感じるのだが,これは一体