依赖管理 - 动态查找哪个文件包含 Ruby 中的当前文件



>上下文

我通过以下方式自动要求目录结构中的所有文件

# 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

问题

有没有一种"干净"的方式来执行这种类型的自动要求,同时动态避免包含调用自动要求器的文件(即 api.rb (?

请记住,当您多次require由特定路径标识的文件时,对require的每个后续调用都将返回false,并且不会重新评估该文件。因此,如果你require其他一切的base.rb本身是require d,进一步证明require它不应该导致重新评估。

让我们用一个例子来演示它。创建一个包含 3 个文件的lib目录。

# 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.rbbase.rb将被评估两次:首先,当它直接执行时;其次,当它被a.rb require时。请注意,当需要时,不会对其进行评估 b.rb .

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

require比较。现在,base.rb仅评估一次,因为尝试在 a.rbb.rbrequire它之前,使用命令行-r开关将文件require d。

$ ruby -I lib -r base -e 'puts :ok'
Evaluated base.rb 1 times
a
b
ok

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
$

相关内容

  • 没有找到相关文章

最新更新