web-dev-qa-db-ja.com

Rails 3のlibフォルダーからモジュール/クラスをロードする最良の方法は?

最新のRails 3リリースはlibからモジュールとクラスを自動ロードしないため、それらをロードする最良の方法は何でしょうか?

Githubから:

A few changes were done in this commit:

Do not autoload code in *lib* for applications (now you need to explicitly 
require them). This makes an application behave closer to an engine 
(code in lib is still autoloaded for plugins);
270
Vincent

Rails 2.3.9以降 には、config/application.rbに設定があり、自動ロードするファイルを含むディレクトリを指定できます。

Application.rbから:

# Custom directories with classes and modules you want to be autoloadable.
# config.autoload_paths += %W(#{config.root}/extras)
248
# Autoload lib/ folder including all subdirectories
config.autoload_paths += Dir["#{config.root}/lib/**/"]

ソース: Rails 3クイックヒント:すべてのサブディレクトリを含むlibディレクトリを自動読み込み、遅延読み込みを回避

Libフォルダーに含まれるファイルは、サーバーの起動時にのみロードされることに注意してください。これらのファイルを快適に自動再読み込みする場合は、以下をお読みください: Rails 3クイックヒント:開発モードでlibフォルダーを自動再読み込み 。永続的なリロードによりマシンの速度が低下するため、これは実稼働環境向けではないことに注意してください。

196
thankful

自動ロードの魔法

自動ロード処理が行われるフォルダを制御するオプションは、他の回答で十分にカバーされていると思います。ただし、必要に応じて自動ロードパスを変更したにもかかわらず、他の誰かが問題をロードしている場合、この回答はこの自動ロードの背後にある魔法の説明を試みます。

そのため、サブディレクトリからものをロードすることになると、注意すべきことや慣習があります。 Ruby/Railsの魔法(今回はほとんどRails)が原因で、何かが発生している理由を理解するのが難しくなることがあります。自動ロードパスで宣言されたモジュールは、モジュール名が親ディレクトリ名に対応する場合にのみロードされます。そのため、lib/my_stuff/bar.rbに次のようなものを入れようとした場合:

module Foo
  class Bar
  end
end

自動的にロードされることはありません。次に、親ディレクトリの名前をfooに変更して、モジュールをパス:lib/foo/bar.rbでホストする場合も同様です。それはあなたのためにそこにあります。別のオプションは、モジュール名で自動ロードするファイルに名前を付けることです。明らかに、その名前のファイルは1つしか存在できません。ものを多くのファイルに分割する必要がある場合は、もちろんその1つのファイルを使用して他のファイルを要求できますが、それはお勧めしません。開発モードでそれらの他のファイルを変更してからRailsは自動的にそれらをリロードできません。ただし、本当に必要な場合は、モジュールを使用するために必要な実際のファイルを指定するモジュール名で1つのファイルを作成できます。したがって、2つのファイル:lib/my_stuff/bar.rblib/my_stuff/foo.rbがあり、前者は上記と同じであり、後者は単一行require "bar"を含んでおり、それはまったく同じように機能します。

追伸もう1つ重要な点を追加する必要があります。最近のように、libディレクトリに何かを自動ロードする必要があるときはいつでも、これがこのプロジェクト専用に実際に開発しているものである場合(通常はいつか、いつかは多くのプロジェクトやgitサブモジュールなどで使用されるコードの「静的な」スニペットになります。この場合、それは間違いなくlibフォルダーにあるはずです)、おそらくその場所はlibフォルダーにはありません。おそらく、アプリフォルダーの下のサブフォルダーに配置する必要があります。これが新しいRails方法の実行方法であると感じています。明らかに、同じ魔法が、あなたがあなたの物を入れる自動ロードパスのどこにでもあるので、これらのものに良いです。とにかく、これはこのテーマに関する私の考えです。あなたは自由に意見を異にすることができます。 :)


更新:魔法の種類について..

セヴェリンが彼のコメントで指摘したように、コアの「モジュールを自動ロードするメカニズム」は確かにRubyの一部ですが、自動ロードのパスはそうではありません。 autoload :Foo, File.join(Rails.root, "lib", "my_stuff", "bar")を実行するためにRailsは必要ありません。そして、モジュールFooを初めて参照しようとすると、モジュールがロードされます。しかし、Railsが行うことは、登録されたフォルダーから自動的にものをロードしようとする方法を提供することです。これは、命名規則について何かを仮定する必要があるように実装されています。そのように実装されていなかった場合、現在ロードされていないものを参照するたびに、すべての自動ロードフォルダー内のすべてのファイルを調べて、参照しようとしているものが含まれているかどうかを確認する必要があります。これにより、オートロードとオートリロードの概念が無効になります。ただし、これらの規則が整っていると、モジュール/クラスから、それが定義されている可能性のある場所をロードしようとして、それをロードできます。

81
Timo

警告: 'lib'フォルダから 'monkey patch'または 'open class'をロードする場合は、 'autoload'アプローチ !!!を使用しないでください。

  • " config.autoload_paths "アプローチ:1か所でのみ定義されたクラスをロードする場合にのみ機能します。一部のクラスが既に別の場所で定義されている場合、このアプローチで再度ロードすることはできません。

  • " config/initializer/load_rb_file.rb "アプローチ:常に機能します!ターゲットクラスが新しいクラスであっても、既存のクラスの「オープンクラス」または「モンキーパッチ」であっても、常に機能します。

詳細については、以下を参照してください: https://stackoverflow.com/a/6797707/445908

41

非常に似ていますが、これはもう少しエレガントだと思います:

config.autoload_paths += Dir["#{config.root}/lib", "#{config.root}/lib/**/"]
28
Brian Armstrong

私の場合、私は単にlib dirの直下にファイルをロードしようとしていました。

Application.rb内で...

require '/lib/this_file.rb' 

コンソールでも動作しませんでした

require './lib/this_file.rb' 

Railsはファイルを完全にロードします。

私はまだかなり初心者であり、なぜこれが機能するのか分かりませんが、機能します。誰かが私にそれを説明したい場合、私はそれを感謝します:Dこれは誰かに役立つことを願っています。

14
Nick Res

同じ問題がありました。ここに私がそれを解決した方法があります。このソリューションは、libディレクトリとすべてのサブディレクトリ(直接だけでなく)をロードします。もちろん、これをすべてのディレクトリに使用できます。

# application.rb
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]
7
hjuskewycz

config.autoload_pathsは機能しません。他の方法で解決します

Rails 3のRubyは、/ libフォルダーからコードを自動再ロード(自動ロード)しません。 ApplicationControllerの中に入れて解決します

Dir["lib/**/*.rb"].each do |path|
  require_dependency path
end 
5
msa7

特定のファイルのみがlibのモジュールにアクセスする必要がある場合は、必要なファイルにrequireステートメントを追加するだけです。たとえば、1つのモデルが1つのモジュールにアクセスする必要がある場合、次を追加します。

require 'mymodule'

model.rbファイルの先頭。

4
Mike Fischer

Rails 5の時点で、libフォルダーをappディレクトリーの下に置くか、代わりにservicespresentersfeaturesなどとしてフォルダーの他の意味のある名前空間を作成し、Railsによる自動ロードのためにappディレクトリーの下に置くことをお勧めします。

これも確認してください GitHub Discussion Link も。

2
Ashik Salman

Libからの読み込みで問題が発生する可能性があるいくつかの理由があります-詳細はこちらをご覧ください- http://www.williambharding.com/blog/technology/Rails-3-autoload-modules-and-classes-in-production /

  • 自動ロードパスを修正
  • スレッドセーフ関連
  • ネーミング関連
  • ...
1
Chris Kimpton

ファイル名を正しく入力してください。

真剣に。クラスはGovernance :: ArchitectureBoardであり、ファイルはlib/governance/architecture_baord.rb(「ボード」のOとAを入れ替えた)であったため、クラスと1時間戦いました。

振り返ってみると明らかですが、それはそれを追跡する悪魔でした。クラス名の変更に基づいてRailsが期待しているファイルでクラスが定義されていない場合、クラスを見つけることができません。

0
David Hempy