Каков наилучший способ требовать все файлы из каталога в 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)