2009-07-11 10 views
2

ruby​​にはファイル全体をロードするか、何もロードしないバージョンrequireがありますか?Rubyに全部または何も必要ありませんか?

問題がトップからロードを開始し、それはあなたが未完了の定義で終わる問題に直面している場合、例えば、以下はまだmodule Cが定義されていない場合でも、class Aをロードする必要とすることである。

class B 
    include C 
end 

私の特別なケースでは、相互依存ファイルの大きなセットと、それらのファイルをロードするローダーがあります。例として、ファイルの集合を4つのファイル(a.rb、b.rb、c.rb、w.rb)に単純にします。以下はそれらのファイルのリストです:

ローダは、現在のファイルのリストを取得し、1つずつ要求して動作します。いずれかのファイルに障害が発生すると、そのファイルはリストに残り、後で再試行されます。コードは次のようなものです:私は最終的にそれがAをロードしたいと思う(簡略化のため詳細の多くを削除)

# In file loader.rb 
files = Dir["*.rb"].reject { |f| f =~ /loader/ } 
files.sort! # just for the purpose of the example, to make them load in an order that causes the problem 
files.reject! { |f| require(f) rescue nil } while files.size > 0 

、そのBがCをロードし、その後、(それをスキップ)のみをロードすることはできません見つけますWがまだ読み込まれていない(スキップしている)のを見つけたら、BとWに戻ります。

この場合、p W.get_fooの出力は、私が欲しいものです["in A", "in B", "in W"]です。

実際には、AをロードしてからBを部分的にロードし、次にCをロードすると、WになるとBがすでに定義されているためロードできます。これにより、不適切な時刻にself.inheritedコードがトリガされ、の出力が["in A", "in W"]に間違って表示され、@fooの未準備値がコピーされます。

オール・オア・ナッシングなので、requireが解決されます。

アイデア?

答えて

5

1つのファイルが別のファイルに依存する場合、そのファイルには依存関係が必要です。例えば、b.rbは次のようになります。

require 'b' 

class W < B 
    @foo.push("in W") 
end 
その後

、外側のロード順もはや事項を、また「全か何もしません:

require 'a' 
require 'c' 

class B < A 
    include C# if C is not already defined, the following line will not get executed although B will be defined. 
    @foo.push("in B") 
end 

w.rbは次のようになります。 "にはアプローチが必要です。 bがロードされると、最初にaの要求が表示され、既にロードされていることを認識し、cが必要です。まだロードされていないことがわかっているためです。 cが再び必要になると、外側のループからそれをスキップします。

注:$ LOAD_PATHに注意し、パスはrequireに渡されます。 Rubyは、パスが同じ場合に必要な重複を認識します。絶対パスの代わりに相対パス($ LOAD_PATHのパスを基準にした相対パス)を使用することをお勧めします。そうしないと、ファイルが2回ロードされる可能性があります。

+0

ありがとう、私は各ファイルで 'require'を使うことができることを知っていましたが、私はそれが_automatic_であることを望んでいました。私は複雑なソリューション(テストするサンドボックスとして2番目のルビーインスタンスを実行しています)を考え出しましたが、これはベストプラクティスであると思われるので、私はそれを実行します:) –

関連する問題