私のアプリの1つをRails 4.2.6からRails 5.0.0にアップグレードしました。 アップグレードガイド によると、オートロード機能は本番環境ではデフォルトで無効になっています。
application.rb
ファイルにすべてのlibファイルをautoloadでロードするので、運用サーバーでは常にエラーが発生します。
module MyApp
class Application < Rails::Application
config.autoload_paths += %W( lib/ )
end
end
今のところ、私はconfig.enable_dependency_loading
をtrue
に設定しましたが、もっと良い解決策があるのだろうか。自動ロードがデフォルトで本番環境で無効になっている理由があるはずです。
自動ロードは、スレッドの安全性のために本番環境では無効になっています。リンクをありがとうございました@Зелёный。
Github で推奨されているように、私はlib
ディレクトリのapp
フォルダにlibファイルを保存することによってこの問題を解決しました。 app
フォルダー内のすべてのフォルダーはRailsによって自動的にロードされます。
Rails 5に移行した後の私の変更点の一覧:
lib
dirをapp
name__に配置します。変更を加えるたびにサーバーを再起動する必要はありません。require
name__ステートメント内の自分のクラスを指しているlib
name__ステートメントはすべて、それらのファイル/ディレクトリ名が正しい場合はすべて自動ロードされるため、require
name__ステートメントをそのままにしておくと自動再ロードが中断される可能性があります。さらに詳しい情報 ここconfig.eager_load = true
を設定して、devでコードロードの問題を積極的に確認してください。Rails.application.eager_load!
を使用してください。Ruby/Railsエクステンションがある場合は、そのコードを古いlib
name__ディレクトリ内に残し、それらをイニシャライザから手動でロードします。これにより、それに依存する可能性がある追加のロジックの前に拡張機能が確実にロードされます。
# config/initializers/extensions.rb
Dir["#{Rails.root}/lib/Ruby_ext/*.rb"].each { |file| require file }
Dir["#{Rails.root}/lib/Rails_ext/*.rb"].each { |file| require file }
Githubのコメントでakostadinovに言及したように、私はちょうどconfig.eager_load_paths
の代わりにconfig.autoload_paths
を使いました: https://github.com/Rails/rails/issues/13142#issuecomment-275492070
# config.autoload_paths << Rails.root.join('lib')
config.eager_load_paths << Rails.root.join('lib')
それは開発と生産環境に働きます。
#{Rails.root}/lib
をRails.root.join('lib')
に置き換えることを提案してくれてありがとう Johan
自動ロードがデフォルトで本番環境で無効になっている理由があるはずです。
これはこの問題についての長い議論です。 https://github.com/Rails/rails/issues/13142
これはlibの自動再読み込みを可能にし、本番環境でも動作します。
P.S私は自分の答えを変えました。今では(ステージのように)カスタム環境でも作業できるように、環境に関係なく自動ロードパスの両方に追加されます
# config/initializers/load_lib.rb
...
config.eager_load_paths << Rails.root.join('lib')
config.autoload_paths << Rails.root.join('lib')
...
ある意味で、これは積極的なオートロード設定を一元化するためのRails 5の統一されたアプローチです。
# config/application.rb
...
config.paths.add Rails.root.join('lib').to_s, eager_load: true
# as an example of autoload only config
config.paths.add Rails.root.join('domainpack').to_s, autoload: true
...
私のようにこれに苦しんでいる人にとっては、ディレクトリをapp/
の下に置くだけでは不十分です。はい、あなたは自動ロードを取得しますが、必要ではありません 再ロード。名前空間の規約を守る必要があります 。
また、初期化子を使用して古いルートレベルのlib
をロードすると、開発中の機能の再ロードが妨げられます。
Libフォルダをappに移動すると問題が解決しましたが、私のTwitter APIは本番環境では動作しませんでした。私は「初期化されていない定数TwitterApi」を持っていて、私のTwitter APIは私のlibフォルダにありました。私のapplication.rbにconfig.autoload_paths += Dir["#{Rails.root}/app/lib"]
がありましたが、フォルダを移動する前はうまくいきませんでした。
これはトリックでした
levの答えを要約すると、mv lib app
は私のすべてのlib
コードをオートロード/オートリロードするのに十分でした。
(Rails 6.0.0beta 3ですが、Rails 5.xでもうまく動くはずです)