要求ruby目录中的所有文件的最佳方法?

Gae*_*bar 339 ruby directory file require

要求ruby目录中的所有文件的最佳方法是什么?

Sam*_*kes 450

怎么样:

Dir["/path/to/directory/*.rb"].each {|file| require file }
Run Code Online (Sandbox Code Playgroud)

  • 有一个微妙的陷阱,不剥离扩展.如果代码调用的其他部分需要'foo',则ruby将再次加载相同的文件,这可能导致虚假错误.我添加了自己的答案,解释了这一点,并展示了如何剥离扩展. (28认同)
  • 根据Pickaxe,.rb扩展名是可选的.从技术上讲,它改变了含义:"require'foo.rb'"需要foo.rb,而"require'foo'"可能需要foo.rb,foo.so或foo.dll. (18认同)
  • @ PeteHodgson的建议不准确.Ruby的`require`不会因`.rb`扩展名的存在与否而混淆.测试在MRI 1.8.7-p374,2.1.5和2.2.0上测试.这个都市传奇来自Rails,其中"聪明"的自动加载展示了他在旧版本中描述的行为(并且可能仍然展示它). (10认同)
  • 这可能是显而易见的,但值得注意的是,删除.rb也需要dir中的任何非.rb文件,这可能是不可取的. (5认同)
  • @Pete,这仍然是真的吗?请参阅下面的[Rene的评论](http://stackoverflow.com/questions/735073/best-way-to-require-all-files-from-a-directory-in-ruby#comment9237243_2231511). (4认同)
  • 在要求之前你需要放弃.rb.除此之外还不错 (3认同)
  • 确保首先对文件进行排序,以免引入由操作系统引起的随机性并保持要求顺序确定性:`Dir["/path/to/directory/*.rb"].sort.each {|file| 需要文件 }` (2认同)

jan*_*dot 337

如果它是相对于执行要求的文件的目录(例如,您要加载lib目录中的所有文件):

Dir[File.dirname(__FILE__) + '/lib/*.rb'].each {|file| require file }
Run Code Online (Sandbox Code Playgroud)

编辑:根据以下评论,更新版本:

Dir[File.join(__dir__, 'lib', '*.rb')].each { |file| require file }
Run Code Online (Sandbox Code Playgroud)

  • 使用File.join可能更安全,而不是对前向/后向斜杠做出假设:`Dir [File.join(File.dirname(__ FILE__),'lib','*.rb')].每个{|文件| require file}` (61认同)
  • 如果您使用的是> = ruby​​ 2.0,则可以使用`__dir__`而不是`File.dirname(__ FILE __)`. (30认同)
  • 您还可以添加所有子目录,如"Dir [File.dirname(__ FILE__)+'/ support/./*.rb'].{{file | require file}` (13认同)
  • 还有require_relative (6认同)
  • @maasha你如何使用`require_relative`来要求目录中的所有文件? (2认同)

小智 98

尝试require_all gem:

  1. http://github.com/jarmo/require_all
  2. https://rubygems.org/gems/require_all

它让你简单地:

require_all 'path/to/directory'
Run Code Online (Sandbox Code Playgroud)

  • 用可以简单地用一行代码替换的 gem 来膨胀你的应用程序是没有意义的。这会增加您的应用程序的加载时间,并在长期内引发更多错误。 (3认同)
  • @panupan请注意,`require_all`的循环依赖解析可以解决源代码中的问题:您拥有不需要依赖项的Ruby源文件.这会关闭手术刀装载的门,让您承受全部或全部装载.这在小型图书馆中不是问题,但是你应该有意识地做出决定. (2认同)

Pet*_*son 52

Dir[File.dirname(__FILE__) + '/../lib/*.rb'].each do |file| 
  require File.basename(file, File.extname(file))
end
Run Code Online (Sandbox Code Playgroud)

如果你没有剥离扩展,那么你最终可能需要两次相同的文件(ruby不会意识到"foo"和"foo.rb"是同一个文件).两次需要相同的文件会导致虚假警告(例如"警告:已经初始化常量").

  • 我的测试结果与Derek说的相同:`require"foo.rb"; 要求"foo";`只会加载`foo.rb`一次. (13认同)
  • 这是真的吗?文档说明:如果某个功能名称已经出现在$"中,则不会加载该功能.文件名转换为绝对路径,因此"需要'a'; 要求'./a'"不会加载a.rb两次.http://www.ruby-doc.org/core/classes/Kernel.html#M001418 (11认同)
  • 不,Ruby的`require`不会因`.rb`扩展名的存在与否而混淆.在MRI 1.8.7-p374,2.1.5和2.2.0上测试.这个都市传奇来自Rails,其中"聪明"的自动加载展示了旧版本中描述的行为(并且可能仍然展示它). (4认同)

met*_*gfu 42

Dir.glob(File.join('path', '**', '*.rb'), &method(:require))
Run Code Online (Sandbox Code Playgroud)

或者,如果要将文件范围加载到特定文件夹:

Dir.glob(File.join('path', '{folder1,folder2}', '**', '*.rb'), &method(:require))
Run Code Online (Sandbox Code Playgroud)

说明:

Dir.glob以块为参数.

method(:require)将返回require方法.

&method(:require)会将方法转换为bloc.

  • 这是一些漂亮的代码.我喜欢没有可见的块. (2认同)

Rya*_*ary 30

最好的方法是将目录添加到加载路径,然后添加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
Run Code Online (Sandbox Code Playgroud)

请注意,前两行返回true意味着两次都加载了相同的文件.使用路径时,即使路径指向同一位置,require也不知道该文件是否已被要求.

在这里,我们将一个目录添加到加载路径,然后需要每个*.rb文件的基名.

dir = "/path/to/directory"
$LOAD_PATH.unshift(dir)
Dir[File.join(dir, "*.rb")].each {|file| require File.basename(file) }
Run Code Online (Sandbox Code Playgroud)

如果你不关心文件被多次需要,或者你的意图只是加载文件的内容,也许load应该用来代替require.在这种情况下使用load,因为它更好地表达了您要完成的任务.例如:

Dir["/path/to/directory/*.rb"].each {|file| load file }
Run Code Online (Sandbox Code Playgroud)


Koe*_*en. 14

我没有像在某些答案中那样连接路径,而是使用File.expand_path:

Dir[File.expand_path('importers/*.rb', File.dirname(__FILE__))].each do |file|
  require file
end
Run Code Online (Sandbox Code Playgroud)

更新:

而不是使用File.dirname你可以做以下事情:

Dir[File.expand_path('../importers/*.rb', __FILE__)].each do |file|
  require file
end
Run Code Online (Sandbox Code Playgroud)

..条的文件名__FILE__.


小智 13

Dir[File.join(__dir__, "/app/**/*.rb")].each do |file|
  require file
end
Run Code Online (Sandbox Code Playgroud)

这将在您的本地计算机和一个不使用相对路径的远程(如Heroku)上递归工作.


Dan*_*ohn 7

在Rails中,您可以:

Dir[Rails.root.join('lib', 'ext', '*.rb')].each { |file| require file }
Run Code Online (Sandbox Code Playgroud)

更新:修正了@Jiggneshh Gohel删除斜线的建议.