Каков наилучший способ требовать все файлы из каталога в ruby?
Каков наилучший способ требовать все файлы из каталога в ruby?
Ответы:
Как насчет:
Dir["/path/to/directory/*.rb"].each {|file| require file }
require
не смущает наличие или отсутствие .rb
расширения. Проверено на МРТ 1.8.7-p374, 2.1.5 и 2.2.0. Эта городская легенда происходит от Rails, где «умная» автозагрузка демонстрирует поведение, которое он описывает в более старых версиях (и может все еще демонстрировать его).
Если это каталог относительно файла, который требует (например, вы хотите загрузить все файлы в каталоге lib):
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 }
Dir[File.join(File.dirname(__FILE__), 'lib', '*.rb')].each {|file| require file }
__dir__
вместо File.dirname(__FILE__)
.
require_relative
чтобы требовать все файлы в каталоге?
Попробуйте гем require_all:
Это позволяет вам просто:
require_all 'path/to/directory'
require_all
разрешение циклических зависимостей решает проблему в вашем исходном коде: у вас есть исходные файлы Ruby, которые не требуют своих зависимостей. Это закрывает дверь при загрузке скальпеля, заставляя вас загружать все или ничего. Это не проблема в небольших библиотеках, но это решение, которое вы должны принимать осознанно.
Dir[File.dirname(__FILE__) + '/../lib/*.rb'].each do |file|
require File.basename(file, File.extname(file))
end
Если вы не удалите расширение, вам может понадобиться один и тот же файл дважды (ruby не поймет, что «foo» и «foo.rb» - это один и тот же файл). Двойной запрос одного и того же файла может привести к ложным предупреждениям (например, «предупреждение: уже инициализированная константа»).
require "foo.rb"; require "foo";
загрузится foo.rb
только один раз.
require
не смущает наличие или отсутствие .rb
расширения. Протестировано на МРТ 1.8.7-p374, 2.1.5 и 2.2.0. Эта городская легенда происходит от Rails, где «умная» автозагрузка демонстрировала поведение, описанное в более старых версиях (и может все еще демонстрировать его).
Dir.glob(File.join('path', '**', '*.rb'), &method(:require))
или, в качестве альтернативы, если вы хотите разместить файлы для загрузки в определенные папки:
Dir.glob(File.join('path', '{folder1,folder2}', '**', '*.rb'), &method(:require))
объяснение:
Dir.glob принимает блок в качестве аргумента.
Метод (: require) вернет метод require.
& method (: require) преобразует метод в блок.
Dir.glob( File.join( File.dirname(__FILE__), '{lib,addons}', 'subfolder', '**', '*.rb' ), &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 }
Вместо объединения путей, как в некоторых ответах, я использую 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
Rails.root.join
ответы также работают, если вы находитесь в рельсах.
В Rails вы можете сделать:
Dir[Rails.root.join('lib', 'ext', '*.rb')].each { |file| require file }
Обновление: исправлено с предложением @Jiggneshh Gohel для удаления слешей.
Rails.root.join('/lib')
, не генерирует правильный путь. Я нашел, что это работает правильно:Dir[Rails.root.join('lib', 'ext', '*.rb')].each { |file| require file }
А как насчет require_relative *Dir['relative path']
?
require_relative *Dir['*.rb']
работать, если есть только один ruby-скрипт. Но если найдено несколько скриптов ruby, вы получитеrequire_relative': wrong number of arguments (4 for 1) (ArgumentError)