web-dev-qa-db-ja.com

RailsイニシャライザRails 6 / Zeitwerkを使用してイニシャライザにプリロードできますか?

アプリの懸念事項をサードパーティのlibに含めることで、アプリの起動時にサルのパッチを適用するイニシャライザを使用しています。基本的に:

# config/initializers/my_initializer.rb

class SomeExternalLib
  include MyConcern1
  include MyConcern2
end

これはRails 5.2.3では正常に機能しますが、Rails 6にアップグレードすると、次の非推奨メッセージが表示されます。

非推奨の警告:初期化により、定数MyConcern1およびMyConcern2がオートロードされました。

これを実行できることは非推奨です。初期化中の自動読み込みは、将来のバージョンのRailsではエラー状態になる予定です。

再ロードしてもアプリケーションは再起動されないため、初期化中に実行されたコードは再度実行されません。したがって、たとえばApplicationHelperを再ロードした場合、予期された変更はその古いModuleオブジェクトに反映されません。

これらの自動ロードされた定数はアンロードされました。

解決策については、「定数の自動読み込みと再読み込み」ガイドを確認してください。 (/Users/myuser/code/myapp/config/environment.rb:7から呼び出されます)

私の懸念はapp/controllers/concerns /にあります。調査の結果、そのパスがオートロードされていないことがわかりましたが、Zeitwerk(Rails 6の新しいオートローダー)に動的にロードさせる方法がわかりません。 here で説明されているSTI自動読み込みのパターンに従ってみましたが、うまくいきませんでした。この非推奨警告に対処する方法はありますか?

10
Glyoko

@Glyokoの回答で説明されているように、依存関係でrequireを使用すると、イニシャライザでのオートロードが防止されます。ただし、@ Puhlzeがコメントで述べたように、これはリロード中に問題を引き起こします。

この投稿Rails.configuration.to_prepareを利用する別のアプローチを見つけました。

例は次のとおりです。

# config/initializers/my_initializer.rb

Rails.configuration.to_prepare do
  class SomeExternalLib
    include MyConcern1
    include MyConcern2
  end
end

これは、開発中のすべてのリクエストの前に実行されますが、本番環境での積極的なロードの前に一度だけ実行されることに注意してください。

編集:リロードでも機能するようです。

4
Joseph Siefers

エラーメッセージをもう少し詳しく読んでみると役に立ちます。

初期化中のオートロードは、将来のバージョンのRailsではエラー状態になる予定です。

変更についての議論は ここ であり、ガイドは ここ です。

要するに、自動ローディングはイニシャライザで行われるべきではなく、これは段階的に廃止されます。解決策は、1)イニシャライザでオートロードする必要があるものを使用しない(推奨)か、2)イニシャライザで依存関係を明示的に要求するかのいずれかです。

だから私はやります:

# config/initializers/my_initializer.rb

require 'my_concern1'
require 'my_concern2'

class SomeExternalLib
  include MyConcern1
  include MyConcern2
end
4
Glyoko