如何在ruby中要求从一个目录中加载所有文件的最佳方法?
怎么样:
Dir["/path/to/directory/*.rb"].each {|file| require file }
Dir[File.dirname(__FILE__) + '/lib/*.rb'].each {|file| require file }
编辑:基于下面的评论,更新后的版本:
Dir[File.join(__dir__, 'lib', '*.rb')].each { |file| require file }
Dir[File.dirname(__FILE__) + '/support/**/*.rb'].each {|file| require file }
。 - jspoonerDir[File.join(File.dirname(__FILE__), 'lib', '*.rb')].each {|file| require file }
。 - Chris__dir__
代替File.dirname(__FILE__)
。 - Christian Bankesterrequire_relative
来引入一个目录中的所有文件? - David Moles尝试使用require_all宝石:
它让你轻松地:
require_all 'path/to/directory'
require_all
库的循环依赖解决方案是为了解决你源代码中的一个问题:你的Ruby源文件没有引用它们的依赖项。这会关闭精细加载(scalpel loading)的可能性,使你只能进行全量加载或不加载。在小型库中这并不是一个问题,但你应该有意识地做出这个决定。 - sheldonhDir[File.dirname(__FILE__) + '/../lib/*.rb'].each do |file|
require File.basename(file, File.extname(file))
end
如果你不去掉文件扩展名,那么你可能会需要同一个文件两次(Ruby无法意识到"foo"和"foo.rb"是同一个文件)。重复需要同一个文件可能会导致虚假的警告(例如:"warning: already initialized constant")。require "foo.rb"; require "foo";
只会加载一次foo.rb
。 - Rene Saarsoorequire
命令不会因为是否存在.rb
文件扩展名而混淆。在MRI 1.8.7-p374、2.1.5和2.2.0上进行了测试。这个谣言来自Rails,那里的“聪明”的自动加载行为在旧版本中呈现出所描述的行为(可能仍然如此)。 - sheldonhDir.glob(File.join('path', '**', '*.rb'), &method(:require))
或者,如果你想将文件的加载范围限定在特定的文件夹中:
Dir.glob(File.join('path', '{folder1,folder2}', '**', '*.rb'), &method(:require))
解释:
Dir.glob方法需要一个块作为参数。
method(:require)将返回require方法。
&method(:require)将把该方法转换为块。
最好的方式是将目录添加到加载路径中,然后require
每个文件的基本名称。这是因为你希望避免意外地两次要求相同的文件--这通常不是期望的行为。文件是否被加载取决于require
之前是否已经看到了传递给它的路径。例如,这个简单的irb会话显示您可以错误地两次要求和加载同一个文件。
$ irb
irb(main):001:0> require 'test'
=> true
irb(main):002:0> require './test'
=> true
irb(main):003:0> require './test.rb'
=> false
irb(main):004:0> require 'test'
=> false
请注意,前两行返回 true
,意味着同一个文件已经被加载了两次。即使路径指向相同的位置,当使用路径时,require
也不知道文件是否已经被加载过。
相反地,在这里,我们将一个目录添加到加载路径中,并要求每个 *.rb 文件的基本名称。
dir = "/path/to/directory"
$LOAD_PATH.unshift(dir)
Dir[File.join(dir, "*.rb")].each {|file| require File.basename(file) }
如果您不关心文件是否被要求多次,或者您的意图只是加载文件的内容,也许应该使用 load
而不是 require
。在这种情况下使用 load,因为它更好地表达了您想要实现的目标。例如:
Dir["/path/to/directory/*.rb"].each {|file| load file }
require
需要加上./
,而require_relative
意识到它们都是指向同一文件的路径。 - NakilonDir[File.join(__dir__, "/app/**/*.rb")].each do |file|
require file
end
这将在您的本地机器和远程 (例如 Heroku) 上递归工作,不使用相对路径。
不同于其他答案中连接路径的方法,我使用了File.expand_path
函数:
Dir[File.expand_path('importers/*.rb', File.dirname(__FILE__))].each do |file|
require file
end
更新:
不必使用File.dirname
,您可以尝试以下方法:
Dir[File.expand_path('../importers/*.rb', __FILE__)].each do |file|
require file
end
..
会剥离文件名中的 __FILE__
。
File.expand_path
似乎是最新最适合的选择。+1 - mswiebodaRails.root.join
的答案也适用。 - nzifnabDir[Rails.root.join('lib', 'ext', '*.rb')].each { |file| require file }
Rails.root
是一个 Pathname
实例,所以你可以在任何 Ruby 环境中执行此操作,而不仅仅是在 Rails 中(注意 Rails.root.join('lib/ext/*.rb')
读起来更加清晰)。 - DMKERails.root.join('/lib')
并不能生成正确的路径。我发现这个可以正常工作:Dir[Rails.root.join('lib', 'ext', '*.rb')].each { |file| require file }
。 - Jignesh Gohel虽然我有点晚了,但我很喜欢这个一行代码的解决方案,让rails包含在app/workers/concerns中的所有内容:
Dir[ Rails.root.join *%w(app workers concerns *) ].each{ |f| require f }
require
并不会因为有或没有.rb
扩展名而混淆。在MRI 1.8.7-p374、2.1.5和2.2.0版本测试过。这个谣言来自于Rails,在旧版本中展示了他所描述的行为,那时候“聪明”的自动加载可能仍然会出现这种情况。 - sheldonh