Rails5 production環境ではautoloadが無効になっている | onox blog

onox blog

Rails5 production環境ではautoloadが無効になっている

March 04, 2019

Rails5ではautoloadが廃止されており、lib配下のファイルはeager_load対象にする必要がある。

背景

development環境では実行できていたlib配下のtaskが、production環境では実行できなかった。

autoload_pathsにlibを追加していたが、

# config/application.rb
config.autoload_paths += %W(#{config.root}/lib)

エラー発生

uninitialized constant NginxTasks::refresh_cache!

原因

題名の通りで、production環境ではautoloadが無効になっているため。Rails5のデフォルト設定だと以下になっている。
ソース: Autoloading is Disabled After Booting in the Production Environment

development:
  autoload: 有効,
  eager_load: 無効,
production:
  autoload: 無効,
  eager_load: 有効,

もう少し詳しく書くと、こういうこと。
ソース: Autoloading and Reloading Constants — Ruby on Rails Guides

development: ファイル実行時(コード読み込み時)にautoload_pathsにあるファイルを自動読み込み。ファイル変更時には再読み込み
production: 一貫性/スレッドセーフを保つため、起動時にeager_load_pathsにあるファイルを一括読み込み

対策

1. eager_load_pathsにlibを加える

これでautoload_pathseager_load_pathsにlib配下が加わるので、development/production環境双方で問題なし。

# config/application.rb
config.paths.add 'lib', eager_load: true

2. autoloadを有効にする

Ruby on Rails Guidesに記載されている通り、autoloadを有効にしてしまえば、

# config/application.rb
config.enable_dependency_loading = true

この書き方でもOK

# config/application.rb
config.autoload_paths += %W(#{config.root}/lib)

ただスレッドセーフの問題を引き起こす可能性があるため、推奨はされてない模様

Not autoloading after boot is a good thing, as autoloading can cause the app to be have thread-safety problems.