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


273

最新の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);

回答:


251

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)

7
のサブツリー全体をオートロードする場合は、@ thankfulの回答にも注意してくださいapp/lib
Tom Harrison、

199
# Autoload lib/ folder including all subdirectories
config.autoload_paths += Dir["#{config.root}/lib/**/"]

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

libフォルダーに含まれるファイルは、サーバーの起動時にのみ読み込まれることに注意してください。これらのファイルを自動的に再読み込みしたい場合は、Rails 3クイックヒント:開発モードでlibフォルダーを自動再読み込みをお読みください。永続的なリロードはマシンの速度を低下させるため、これは本番環境を対象としたものではないことに注意してください。


リンクは死んでいる
Besi

84

オートロードの魔法

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

したがって、サブディレクトリからのものをロードすることになると、注意すべきことや慣習があります。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"それでも同じように機能します。

PSもう1つ重要なことを追加せざるをえません。最近、自動ロードする必要があるlibディレクトリに何かを置きたいときはいつでも、これが私が実際にこのプロジェクトのために実際に開発しているものである場合、それは通常、いつか多くのプロジェクトやgitサブモジュールなどで使用されるコードの「静的な」スニペットに変換します。その場合は、必ずlibフォルダーに配置する必要があります)、おそらくその場所はlibフォルダー内にありません。多分それはappフォルダーの下のサブフォルダーにあるべきです。これは物事を行うための新しいRailsの方法だと感じています。言うまでもなく、オートロードパスのどこにものを置いても、同じ魔法が働いているので、これらのことに適しています。とにかく、これはこの件に関する私の考えです。あなたは反対することができます。:)


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

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


1
なぜこのRubyの魔法なのですか?Rubyは、(未定義の)定数にアクセスするときにロードされるファイルをコマンドするために使用できるModule#autoload関数を提供します(ruby-doc.org/core-1.9.3/Module.html#method-i-autoloadを参照)。モジュール/クラス名とディレクトリ/ファイルのマッチングは、私の意見ではRails / ActiveSupportで行われます(例:github.com/rails/rails/blob/…)。私が間違っている?
セベリン

はい、あなたは正しいと思います。Zabbaがその「欠陥」を指摘したとき、私は急いで元の答えを「訂正」できませんでした。この問題を明確にするために、回答をもう少し更新しましょう。
ティモ

1
私は30分ほど過ごしました。Sprockets :: JSRender :: Processorを自動ロードする必要がありました。そのパスは、rails consoleに入り、 "Sprockets :: JSRender :: Processor" .underscoreを実行し、それが "sprockets / js_render / processor"(.rbが追加されている)HTHだと気づかずに見つけることができます。
pedz

あなたはちょうど私の正気を救った。〜安心の深いため息〜共有してくれてありがとう:)
ブレンデン2013

この最も役立つコメントをありがとう。あなたのコメントを読むまで、なぜいくつかのモジュールがそれらのように動作していたのか理解できませんでした。あなたに祝福を!
mjnissim 2013年

41

警告:「lib」フォルダから「モンキーパッチ」または「オープンクラス」をロードする場合は、「オートロード」アプローチを使用しないでください!!!

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

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

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


6
これは理解すべき重要な違いです。これをありがとう。
タイラーコリアー2013年


18

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

application.rb内...

require '/lib/this_file.rb' 

コンソールでも動作しなかった後、試したところ

require './lib/this_file.rb' 

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

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


2
これは、。/ lib / this_file.rbが現在のディレクトリ(Railsコンソールの場合はRailsルート)を検索し、/ lib / this_file.rbがそれを絶対パスとして検索するためです。例:./lib/this_file.rb = /var/www/myrailsapp/lib/this_file.rb、/lib/this_file.rb = /lib/this_file.rb
Jason

7

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

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

5
これには、Railsのネームスペース規則を完全に破壊するという厄介な副作用があります。AutoloadルックアップでFooを定義するlib / foo.rbの前にBar :: Fooを定義するlib / bar / foo.rbが表示されるExpected lib/bar/foo.rb to define constant Foo場合、Fooを参照してlib / foo.rbをロードしようとすると、混乱するエラーが発生します。絶え間ない。
ジェイコブ

5

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

Ruby on rails 3は、/ libフォルダーからコードを自動的に再読み込み(autoload)しません。中に入れて解決ApplicationController

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

4

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

require 'mymodule'

model.rbファイルの先頭。


50
requireRailsアプリ内では使用しないでくださいActiveSupport::Dependencies。コードを適切に[アン]ロードできないためです。代わりにconfig.autoload_paths、上記の答えのように使用し、必要に応じてインクルード/エクステンドする必要があります。
ben_h 2010

13
@マイクありがとうございます。私はあなたがしたことをするつもりでした、それが悪い理由の説明を見るのは良かったです。答えを削除しなかったおかげでありがとう。
pupeno

モジュールを1つだけロードしたい場合は、「mymodule」をインクルードしますか?
Mike

1
@ben_h requireRailsアプリのどこからでもアクセスできますか?requireレーキタスクで、私は現在、-と-にincludeあるモジュールに住んでいlib/ます。私はそれをしてはいけませんか?
Dennis

@ben_h私の検索は、それがrequireあなたのlib/コードに共通していることを明らかにします(例えば、このブログ投稿このSO回答)。全体についてはまだよくわかりません。使用しないという主張の背後にあるより多くの証拠を与えることができますrequireか?
Dennis

2

ファイル名のスペルを正しくしてください。

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

振り返ってみると明らかなようですが、それは悪魔が追跡していました。クラス名が変更されたことに基づいてRailsがクラスにあると予期しているファイルでクラスが定義されていない場合、クラスは検出されません。


2

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

このGitHubディスカッションリンクも確認しください。


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