0

環境

ディレクトリ構造内のすべてのファイルを自動要求しています

# base.rb
dir = File.dirname(__FILE__)
path = File.join(dir, '**', '*.rb')
Dir[path].each { |file| require File.expand_path(file, __FILE__) }

require別のファイルのステートメントを介してこのスニペットを呼び出していますapi.rb

問題

このコード スニペットには、自身 ( base.rb) とapi.rb.

質問

auto-require'er を呼び出したファイル (つまりapi.rb) を動的に含めないようにしながら、このタイプの auto-requiring を行う「クリーンな」方法はありますか?

4

2 に答える 2

1

特定のパスで識別されたファイルをrequire2回以上呼び出すと、後続の各呼び出しrequireが返さfalseれ、ファイルが再評価されないことに注意してください。結果として、他のすべてbase.rbであるあなた自身がdである場合、それにさらに注意を払うことは再評価につながるべきではありません。requirerequirerequire

例を使ってデモンストレーションしましょう。lib内部に3つのファイルを含むディレクトリを作成します。

# lib/a.rb

  require 'base'
  puts :a

# lib/b.rb

  require 'base'
  puts :b

# lib/base.rb

  $counter ||= 0
  puts "Evaluated base.rb #{$counter += 1} times"
  dir = File.dirname(__FILE__)
  path = File.join(dir, '**', '*.rb')
  Dir[path].each { |file| require File.expand_path file }

直接実行lib/base.rbします。base.rb2回評価されます。1回目は、直接実行されたときです。第二に、それがrequireによってdであるときa.rb。から必要な場合は評価されないことに注意してくださいb.rb

$ ruby -I lib lib/base.rb 
Evaluated base.rb 1 times
Evaluated base.rb 2 times
a
b

それをすることと比較してくださいrequire。これは、コマンドラインスイッチを使用してファイルdを取得する前にbase.rb試行されたため、一度だけ評価されrequireます。a.rbb.rbrequire-r

$ ruby -I lib -r base -e 'puts :ok'
Evaluated base.rb 1 times
a
b
ok
于 2013-01-22T20:51:00.323 に答える
0

Kernel.caller は、現在の実行スタックを文字列の配列として返します。その配列で見つけたファイル名で require を呼び出すことを避けることができます。同じベース名を持つ複数のファイルは、これをつまずかせます。祖先ファイルのより正確なリストを取得する方法がわかりません。

$ head *.rb
==> A.rb <==
require 'base'
puts :A

==> B.rb <==
require 'base'
puts :B

==> CA.rb <==
require 'base'
puts :CA

==> base.rb <==
dir = File.dirname(__FILE__)
path = File.join(dir, '**', '*.rb')
required = caller.map { |frame| /^(.+):\d+:in `require'$/.match(frame) and File.basename $1 }.compact
Dir[path].each { |file| required.include?(File.basename file) or require File.expand_path file }
$ ruby A.rb
B
CA
A
$ ruby B.rb
A
CA
B
$ ruby CA.rb
A
B
CA
$ ruby base.rb
B
CA
A
$
于 2013-03-04T01:09:14.367 に答える