Rails 5:本番環境でlibファイルをロードする


128

アプリの1つをRails 4.2.6からRails 5.0.0にアップグレードしました。アップグレードガイドは、オートロード機能はデフォルトで生産で無効になっていることを、述べています。

ファイルにautoloadを使用してすべてのlibファイルをロードするため、今では常に本番サーバーでエラーが発生しapplication.rbます。

module MyApp
    class Application < Rails::Application
        config.autoload_paths += %W( lib/ )
    end
end

今のところはに設定しconfig.enable_dependency_loadingましたtrueが、これに対するより良い解決策があるかどうか疑問に思います。本番環境ではデフォルトでオートローディングが無効になっている理由があるはずです。


クレイジーなこと、そしてドキュメントはまだauto_loadをするようにあなたに言っています 新しいアプリの本番環境で何が問題になっているのか非常に混乱しました。そして、Rails 5で学習を始めて以来、移行ガイドを読みませんでした。うまくいけばこれを解決するためにドキュメントの問題を提出しました:github.com/rails/rails/issues/27268
akostadinov

1
驚いたことに、私はlibdirに2つのファイルを持っています。1つのファイルはランタイムで簡単に利用できますが、別のファイルは手動で必要になる必要があります:D
イリュージョニスト

@Tobiasどんな解決策にたどり着きましたか?
ジオボーイ

@geoboy Validatorsコードが自動的に読み込まれるので、app /ディレクトリのフォルダにコード(など)を直接グループ化します。
トビアス

ここでは、適切なファイルパスとクラス定義について説明します。Rails5.2では、ファイルパス:app/services/paylinx/paylinx_service.rbクラス定義:が機能しmodule Paylinx class PaylinxService end endます。私はこれらのautoload_pathsものを試しました。うまくいきません。
NamNamNam

回答:


161

Rails 5に移行した後の変更点のリスト:

  1. app内のすべてのコードはdevに自動ロードされ、eagerはprodにロードさlibれるappため、dirを配置します。最も重要なのは開発時に自動ロードされるため、変更を加えるたびにサーバーを再起動する必要はありません。
  2. require内部の独自のクラスを指すステートメントを削除libします。ファイル/ディレクトリの名前が正しい場合は、すべて自動ロードされるためですrequire。ステートメントを残すと、自動再ロードが中断される可能性があります。詳細はこちら
  3. config.eager_load = trueすべての環境で設定して、devでコードの読み込みの問題を熱心に確認してください。
  4. Rails.application.eager_load!「循環依存」エラーを回避するために、スレッドで遊ぶ前に使用してください。
  5. ruby / rails拡張機能がある場合は、そのコードを古いlibディレクトリに残し、イニシャライザから手動でロードします。これにより、拡張機能に依存する可能性がある次のロジックの前に、拡張機能が確実にロードされます。

    # 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 }
    

8
では、どのようにlibフォルダを使用するのでしょうか。libつまり、dirをappdirに移動することは、一種の回避策のように思えます。
Martin Svoboda

3
/app/lib/ファイル/クラスを配置し、それはオートロードではありません。レール5.1でテスト済み、新しいプロジェクト
Tim Kretschmer

29
春を止める必要があることは注目に値します。すべてをapp / lib /に移動し、コンソールからクラスを使用できないのはなぜかと思って少し時間を無駄にしました。
スプリングス

1
次の行はどこに行くでしょうRails.application.eager_load!
Steven Aguilar

1
これはうまくいくかもしれませんが、最善の解決策ではありません。フォルダ構造もセマンティックです。内のlibものは、appディレクトリ内のものとは異なる、プロジェクトへの認識された親密さを持っています。他のいくつかの答えはこれよりも優れています。
CWitty

84

githubコメントでakostadinovに言及config.eager_load_pathsするのではなく、単に使用しましたconfig.autoload_pathshttps : //github.com/rails/rails/issues/13142#issuecomment-275492070

# config.autoload_paths << Rails.root.join('lib')
config.eager_load_paths << Rails.root.join('lib')

開発環境と本番環境で動作します。

に置き換える提案をJohanに感謝#{Rails.root}/libRails.root.join('lib')ます!


3
魅力のように機能します。構文が気に入らなかったので、に変更しましたconfig.eager_load_paths << Rails.root.join('lib')
3limin4t0r 2017

2
私にはそれが最良の答えでした。私のプロジェクトはRails 5.2でゼロから始め、/ libフォルダーは/ appフォルダーの外に作成されました。移動する理由はわかりませんでした。
Samir Haddad

1
うん、これはうまくいく!Railsの開発者は、libの読み込みの問題を引き起こすことを本当に楽しんでいるようです:Dまで次回まで!
ダミアンロシュ

To Rails 5.2 は、凍結された配列なconfig.eager_load_paths += [Rails.root.join('lib')]ので代わりに 使用しますconfig.eager_load_paths
William Wong Garay

@WilliamWongGaray config.eager_load_pathsは、イニシャライザで変更しようとすると読み取り専用になります。パスを追加application.rbすると、両方の方法で機能します。
のMichałザレウスキー

31

スレッドの安全性のため、本番環境では自動ロードは無効になっています。リンクをありがとう@Зелёный

Githubで推奨されているようにlib、自分のappディレクトリのフォルダーにlibファイルを保存することで、この問題を解決しました。フォルダー内のすべてのフォルダーは、Railsによって自動的にロードされます。app


6
あなたはGitHubの上の長いディスカッションスレッドを通じて掘るしたくない場合は、ここで蒸留説明を見つけることができます:collectiveidea.com/blog/archives/2016/07/22/...
アーネスト

7
私はを使用しましたconfig.eager_load_paths << "#{Rails.root}/lib"。推奨されるRailsアプリの構造に従うには、IMOの方が適しています。
akostadinov 16

2
libsを置くapp/libことは、railsメンバーgithub.com/rails/rails/issues/13142#issuecomment-275549669
eXa

4
これlibはその目的が完全に台無しになる。私は、tenderloveまたはDHHが鳴り響くのを待ちます。その間、(個人的に)@Lev Lukomskyの答えを使用することをお勧めします。
Josh Brody

@JoshBrody私の意見では、/libディレクトリはまったく必要ないということです。サードパーティのライブラリはほとんどの場合宝石であり、そうでない場合は作成された宝石があるはずです。他のファイルについては、/appディレクトリに特定のフォルダを作成します。例えばvalidators
トビアス

22

本番環境ではデフォルトでオートローディングが無効になっている理由があるはずです。

この問題についての長い議論はここにあります。https://github.com/rails/rails/issues/13142


1
このディスカッションは、私が遭遇した主題に関する情報のソースですが、長く読んでも、最高です。
ジェイソン

12

これにより、lib autoreloadが可能になり、本番環境でも機能します。

PS私は私の答えを変更しました。今では、カスタム環境(ステージなど)でも作業できるように、環境に関係なく、自動ロードパスの両方に追加されています。

# config/initializers/load_lib.rb
...
config.eager_load_paths << Rails.root.join('lib')
config.autoload_paths << Rails.root.join('lib')
...

2
これで問題が解決する理由を教えてください。
Stuart.Sklinar

@ Stuart.Sklinarこれにより、libの自動再読み込みが可能になり、本番環境でも機能します。PS私は私の答えを変更しました。今では、環境に関係なく、両方の熱心なオートロードパスに追加され、カスタム環境でも(ステージのような)作業が可能になります
srghma

1
(答えで)展開できますか?コードのみの回答は、なぜ「そのように」実行する必要があるのか​​を理解するのに実際には役立ちません-私はRuby開発者ではないので、SOを片付けるのを助けるだけです。「コードのみの回答」にコメントを追加すると、実際のコンテキストがわかります。
Stuart.Sklinar

1
@ Stuart.Sklinar確実
srghma 2018年

6

config / application.rbファイルのconfig.autoload_pathsconfig.eager_load_pathsに変更するだけです。Rails 5では、本番環境ではデフォルトで自動読み込みが無効になっているためです。詳細については、リンクをクリックしてください

 #config.autoload_paths << "#{Rails.root}/lib"
  config.eager_load_paths << Rails.root.join('lib')

環境の開発と運用の両方で機能します。


4

ある意味で、ここではRails 5の統合されたアプローチで、eagerとautoloadの構成を一元化します。同時に、eagerの負荷が構成されている場合は常に必要なautoloadパスを追加します。そうしないと、正しく機能しません。

# 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
...


0

libフォルダーをappに移動すると問題が解決しましたが、私のTwitter APIは本番環境では実行できませんでした。「初期化されていない定数TwitterApi」があり、Twitter APIはlibフォルダーにありました。私はconfig.autoload_paths += Dir["#{Rails.root}/app/lib"]自分のapplication.rbにありましたが、フォルダーを移動する前に機能しませんでした。

これはトリックをしました


-6

Levの答えを要約mv lib appすると、私のlibコードをすべて自動ロード/自動再ロードするには十分でした。

(rails 6.0.0beta3ですが、rails 5.xでも問題なく動作します)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.