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

问题描述 投票:0回答:12

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

ruby file directory require
12个回答
494
投票

怎么样:

Dir["/path/to/directory/*.rb"].each {|file| require file }

365
投票

如果它是一个相对于需要的文件的目录(例如,你想加载 lib 目录中的所有文件):

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

编辑: 基于以下评论,更新版本:

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

108
投票

尝试 require_all gem:

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

它让你简单:

require_all 'path/to/directory'

53
投票
Dir[File.dirname(__FILE__) + '/../lib/*.rb'].each do |file| 
  require File.basename(file, File.extname(file))
end

如果你不去掉扩展名,那么你可能最终需要同一个文件两次(ruby 不会意识到“foo”和“foo.rb”是同一个文件)。两次请求同一个文件可能会导致虚假警告(例如“警告:已初始化常量”)。


47
投票
Dir.glob(File.join('path', '**', '*.rb'), &method(:require))

或者,如果您想将文件限定为加载到特定文件夹:

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

解释:

Dir.glob 以一个块作为参数。

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

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


35
投票

最好的方法是将目录添加到加载路径,然后

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
。在这种情况下使用负载,因为它能更好地表达您要完成的任务。例如:

Dir["/path/to/directory/*.rb"].each {|file| load file }

17
投票

我没有像某些答案那样连接路径,而是使用

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__
的文件名。


17
投票
Dir[File.join(__dir__, "/app/**/*.rb")].each do |file|
  require file
end

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


8
投票

在 Rails 中,您可以:

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

更新:根据@Jiggneshh Gohel 删除斜杠的建议进行了更正。


3
投票

我迟到了几年,但我有点喜欢这个单线解决方案,我曾经让 Rails 将所有内容包含在 app/workers/concerns 中:

Dir[ Rails.root.join *%w(app workers concerns *) ].each{ |f| require f }


0
投票

所有这些答案都很棒。要补充一点,如果你想自动执行此操作,你可以使用 Zeitwerk,这是 Rails 用来加载文件的工具。

require 'zeitwerk'
loader = Zeitwerk::Loader.new
loader.push_dir('main/src/dir')
loader.setup

然后一切都可以访问一切


-2
投票

那么:

require_relative *Dir['relative path']
?

© www.soinside.com 2019 - 2024. All rights reserved.