如何在Ruby中读取多个文件?

时间:2017-07-10 20:40:28

标签: ruby

我需要一行可以执行以下操作的代码:

skewY

但对于多个文件......这不起作用:

instance_eval(IO.read(File.expand_path('../../policyfiles/base.rb',   __FILE__)))

关于如何做到这一点的任何想法?

1 个答案:

答案 0 :(得分:1)

如果您有一个列表并希望对每个元素执行操作,请使用each

policy_files = ['../../policyfiles/base.rb', '../../policyfiles/app.rb']
policy_files.each { |file|
    instance_eval(IO.read(File.expand_path(file,   __FILE__)))
}

但是应该避免裸instance_eval。它将加载这些文件的内容,就像它们在当前范围内一样。任何全局变量都会超越你自己和彼此。例如......

$ cat policy.rb
foo = 42

def bar
    99
end

$ cat test.rb
foo = 23
instance_eval(IO.read("policy.rb"))

puts foo
puts bar

$ ruby ~/tmp/test.rb
42
99

因为instance_eval在test.rb的范围内运行test2.rb的内容,包括foo = 42。惊喜!

而是使用require_relative。这是加载相对文件的工作,但它不会混淆全局变量。你只会得到方法。

policy_files.each { |file|
    require_relative(file)
}

现在当我们做同样的事情,但是require_relative,你的全局变量是安全的。

$ cat policy.rb
foo = 42

def bar
    99
end

$ cat test.rb
foo = 23
require_relative("policy.rb")

puts foo
puts bar

$ ruby ~/tmp/test.rb
23
99

现在,策略文件中的全局变量不会破坏调用者。

require_relative还有一个额外的好处,就是它只会加载一个一次的给定文件。这意味着任何代码都可以安全地加载这些文件,而无需考虑是否已经加载了其他文件。

请注意,策略的用户必须加载基本策略似乎很奇怪。我不能肯定地说不知道这些文件是做什么的,但我怀疑app.rb应该处理加载base.rb。

另请注意,使用相对路径可能不是最好的选择。如果你重新组织你的代码文件,他们都会破坏。相反,consider adding the top level library directory to $LOAD_PATH

lib_dir = ...whatever you need to figure this out...
$LOAD_PATH.unshift(lib_dir)

然后,假设policyfiles/位于库树的顶部,您可以从项目中的任何文件中require("policyfiles/app.rb"),无论其位置如何。