🥺
Railsのconfig.eager_loadはRakeタスクには影響しない
何が起きたのか
タイトルの通りですが、Railsで config.eager_load
を true
にしてもRakeタスクではeager loadingが無効になります。
config/environments/production.rb
config.eager_load = true
パフォーマンスのためにそういう判断になっているようです。
Rakeタスクではすべてのクラスが必要ないことも多いと思われるのでそういうことなのでしょう。
雑に確認した範囲では少なくとも4.0から現状最新の7.0までそうなっていました。今後もきっとこの挙動は続きそうです。
何が問題か
eager loadingされていないと何が問題なのでしょうか?
クラスがロード済みであることに依存しているロジックがある場合にうまく動かなかったりマルチスレッド処理があるとエラーになったりします。
# 名前空間下の定数全てを取りたいときとか
Foo.constants
解決するには
少々起動が遅くなったとしてもそんなに大きくないアプリケーションではeager loading出来たほうが便利なこともありますよね。
Rails 6.1以降では config.rake_eager_load
を設定することで解決できます。
config.rake_eager_load = true
これを読んでいる賢明なる皆様はきっとRails 6.1未満という化石を使っていることはないと思うのですが、Rails 6.1未満でどうすればよいかという案をいくつか書いておきます。
- Rails 6.1以上にアップデートして
config.rake_eager_load
を設定する - 必要なRakeタスクで
Rails.application.eager_load!
を呼ぶ - 必要なクラスを自前でロードする
- 以下のようなフックを仕込んで
config.rake_eager_load
を再現するconfig/application.rb# 以下はRails 6.1未満で `rake_eager_load` を疑似的に再現するための実装 config.rake_eager_load = nil rake_tasks do if Rails.gem_version >= Gem::Version.new("6.1.0") raise "Rails 6.1以降では不要なのでこのコードを削除してください" end config.after_initialize do self.eager_load! if self.config.rake_eager_load end end
config/environments/production.rbconfig.rake_eager_load = true
まとめ
今回は4の方法で回避しました。
Railsのバージョンアップしようね。
Discussion