間のすべての主要な違いがあるload
とrequire
のRuby on Railsのアプリケーションでは?それとも、両方とも同じ機能を持っていますか?
回答:
require
定義されたすべての検索パスでライブラリを検索し、入力したファイル名に.rbまたは.soを追加します。また、ライブラリが1回だけ含まれるようにします。したがって、アプリケーションでライブラリAとBが必要であり、ライブラリBでライブラリAも必要な場合、Aも1回だけロードされます。
ではload
、あなたはライブラリのフルネームを追加する必要があり、それはあなたが呼び出すたびにロードされるload
-それは、すでにメモリ内にある場合でも。
require
$LOADED_FEATURES
($"
)グローバル配列を介してすでにロードされているものを追跡load
します。これは無視されます。
もう一つの違いKernel#require
とはKernel#load
つまりKernel#load
、あなたが匿名の空のモジュールにロードされたコードをラップすることができ、オプションの二番目の引数を取ります。
残念ながら、それはあまり役に立ちません。まず、load
グローバル名前空間にアクセスするだけで、edコードがモジュールから簡単に抜け出すことができます。つまり、のようなモンキーパッチを適用できclass ::String; def foo; end end
ます。そして第二に、load
コードをラップするモジュールを返さないので、基本的にObjectSpace::each_object(Module)
手でそれを釣り上げる必要があります。
Kernel#load
別の議論があるとは
load
グローバル名前空間にアクセスするだけで、edコードがモジュールから簡単に抜け出すことができます。つまり、のようなモンキーパッチを適用できclass ::String; def foo; end end
ます。そして第二に、load
コードをラップするモジュールを返さないので、基本的にObjectSpace::each_object(Module)
手でそれを釣り上げる必要があります。
Railsアプリケーションを実行していて、Gemfileに、「require:false」オプションを使用して作成した特定のカスタムgemがありました。RailsサーバーまたはRailsコンソールをロードすると、イニシャライザーでgemを要求でき、gemがロードされました。しかし、rspecとcapybaraでスペック機能テストを実行すると、ロードエラーが発生しました。そして、テストの実行時にGemが$ LOAD_PATHに見つからなかった理由に完全に戸惑いました。
そこで、load、require、rubygems、bundleが相互作用するさまざまな方法をすべて確認しました。そして、これらは私が私の特定の問題の解決策を発見するのを助けた私の発見の要約です:
負荷
1)rubyファイルへの絶対パスを渡すと、そのファイル内のコードが実行されます。
load('/Users/myuser/foo.rb')
2)ロードする相対パスを渡すことができます。ファイルと同じディレクトリにいる場合は、次のように検索されます。
> load('./foo.rb')
foo.rb loaded!
=> true
ただし、load()を使用して別のディレクトリからファイルを読み込もうとすると、現在の作業ディレクトリ(./など)に基づく相対パスでファイルが見つかりません。
> load('./foo.rb')
LoadError: cannot load such file -- foo.rb
3)上記のように、loadは常にtrueを返します(ファイルをロードできなかった場合は、が発生しますLoadError
)。
4)グローバル変数、クラス、定数、およびメソッドはすべてインポートされますが、ローカル変数はインポートされません。
5)同じファイルでloadを2回呼び出すと、そのファイルのコードが2回実行されます。指定されたファイルが定数を定義している場合、その定数を2回定義し、警告を生成します。
6)$ LOAD_PATHは、絶対パスの配列です。loadにファイル名だけを渡すと、$ LOAD_PATHをループして、各ディレクトリでファイルを検索します。
> $LOAD_PATH.push("/Users/myuser")
> load('foo.rb')
foo.rb loaded!
=> true
必要とする
1)同じファイルでrequireを2回呼び出すと、実行されるのは1回だけです。また、相対パスで1回、絶対パスで1回参照すると、同じファイルを2回ロードしないようにするのも賢明です。
2)requireは、ファイルが実行された場合はtrueを返し、実行されなかった場合はfalseを返します。
3)requireは、グローバル変数$ LOADED_FEATURESにすでにロードされているファイルを追跡します。
4)ファイル拡張子を含める必要はありません:
require 'foo'
5)requireはfoo.rbを検索しますが、foo.so、foo.o、foo.dllなどのダイナミックライブラリファイルも検索します。これは、rubyからCコードを呼び出す方法です。
6)現在のディレクトリはデフォルトで$ LOAD_PATHにないため、requireは現在のディレクトリをチェックしません。
7)require_relativeは、プロセスの作業ディレクトリではなく、現在のファイルからの相対パスを取ります。
Rubygems
1)Rubygemsは、gemと呼ばれるRubyライブラリのインストールを簡単に管理するために設計されたパッケージマネージャーです。
2)コンテンツをzipファイルとしてパッケージ化します。このファイルには、コードでインポートできる一連のルビーファイルやダイナミックライブラリファイルが、いくつかのメタデータとともに含まれています。
3)Rubygemsは、デフォルトのrequireメソッドを独自のバージョンに置き換えます。そのバージョンは、$ LOAD_PATHのディレクトリに加えて、インストールされているgemを調べます。Rubygemsがgemでファイルを見つけると、そのgemを$ LOAD_PATHに追加します。
4)gem installコマンドは、gemのすべての依存関係を把握し、それらをインストールします。実際、gem自体をインストールする前に、gemのすべての依存関係をインストールします。
バンドラー
1)Bundlerを使用すると、プロジェクトに必要なすべてのgemを指定でき、オプションでそれらのgemのバージョンを指定できます。次に、bundleコマンドは、これらすべてのgemとその依存関係をインストールします。
2)Gemfileというファイルで必要なgemを指定します。
3)bundleコマンドは、Gemfile.lockにリストされているすべてのgemを、リストされている特定のバージョンでインストールします。
4)コマンドの前にbundle execを置くと、例えばbundle exec rspecは、requireがGemfile.lockで指定されたバージョンのgemをロードすることを保証します。
レールとバンドラー
1)config / boot.rbで、require'bundler / setup 'が実行されます。Bundlerは、RubyがGemfile内のすべてのgem(およびそれらのすべての依存関係)を確実に検出できるようにします。require'bundler / setup 'は自動的にGemfileを検出し、Gemfile内のすべてのgemをRubyで利用できるようにします(技術用語では、gemを「ロードパス」に配置します)。これは、「rubygems」を必要とするいくつかの追加の機能を追加するものと考えることができます。
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
2)コードがRubyで利用できるようになったので、必要なgemを要求できます。たとえば、「シナトラ」を要求できます。依存関係がたくさんある場合は、「Gemfile内のすべてのgemが必要です」と言うことをお勧めします。これを行うには、require'bundler / setup 'の直後に次のコードを配置します。
Bundler.require(:default)
3)デフォルトでは、Bundler.requireを呼び出すと、Gemfile内の各gemが必要になります。Gemfileの行にgem'foo '、:require => falseと記載されている場合、fooがインストールされていることを確認しますが、requireは呼び出されません。gemを使用する場合は、require( 'foo')を呼び出す必要があります。
したがって、この幅広い知識を踏まえて、テストの問題に戻り、Bundler.setupがgemを$ LOAD_PATHに追加したため、rails_helper.rbでgemを明示的に要求する必要があることに気付きましたが、必要なものは次のとおりです。 。そして、問題は解決されました。
require
、load
またはautoload
Rubyで?を