Was ist der beste Weg, um alle Dateien aus einem Verzeichnis in Ruby zu benötigen?
Was ist der beste Weg, um alle Dateien aus einem Verzeichnis in Ruby zu benötigen?
Antworten:
Wie wäre es mit:
Dir["/path/to/directory/*.rb"].each {|file| require file }
require
ist nicht durch das Vorhandensein oder Fehlen der .rb
Erweiterung verwirrt . Getestet auf MRT 1.8.7-p374, 2.1.5 und 2.2.0 getestet. Diese urbane Legende stammt von Rails, wo "cleveres" Autoloading das Verhalten zeigte, das er in älteren Versionen beschreibt (und möglicherweise noch zeigt).
Wenn es sich um ein Verzeichnis handelt, das sich auf die Datei bezieht, die die Anforderungen erfüllt (z. B. möchten Sie alle Dateien in das lib-Verzeichnis laden):
Dir[File.dirname(__FILE__) + '/lib/*.rb'].each {|file| require file }
Bearbeiten: Basierend auf den Kommentaren unten, eine aktualisierte Version:
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__
anstelle von verwenden File.dirname(__FILE__)
.
require_relative
, um alle Dateien in einem Verzeichnis zu benötigen?
Probieren Sie das Juwel require_all aus:
Sie können einfach:
require_all 'path/to/directory'
require_all
die zyklische Abhängigkeitsauflösung ein Problem in Ihrem Quellcode umgeht : Sie haben Ruby-Quelldateien, für die keine Abhängigkeiten erforderlich sind. Dies schließt die Tür beim Laden des Skalpells und verpflichtet Sie zum Alles-oder-Nichts-Laden. In kleinen Bibliotheken ist das kein Problem, aber es ist eine Entscheidung, die Sie bewusst treffen sollten.
Dir[File.dirname(__FILE__) + '/../lib/*.rb'].each do |file|
require File.basename(file, File.extname(file))
end
Wenn Sie die Erweiterung nicht entfernen, benötigen Sie möglicherweise zweimal dieselbe Datei (Ruby merkt nicht, dass "foo" und "foo.rb" dieselbe Datei sind). Das zweimalige Anfordern derselben Datei kann zu falschen Warnungen führen (z. B. "Warnung: bereits initialisierte Konstante").
require "foo.rb"; require "foo";
Wird foo.rb
nur einmal geladen .
require
ist nicht durch das Vorhandensein oder Fehlen der .rb
Erweiterung verwirrt . Getestet auf MRT 1.8.7-p374, 2.1.5 und 2.2.0. Diese urbane Legende stammt von Rails, wo "cleveres" Autoloading das in älteren Versionen beschriebene Verhalten zeigte (und es möglicherweise noch zeigt).
Dir.glob(File.join('path', '**', '*.rb'), &method(:require))
oder alternativ, wenn Sie die Dateien in bestimmte Ordner laden möchten:
Dir.glob(File.join('path', '{folder1,folder2}', '**', '*.rb'), &method(:require))
Erläuterung:
Dir.glob nimmt einen Block als Argument.
Methode (: erfordern) gibt die require-Methode zurück.
& method (: require) konvertiert die Methode in einen Block.
Dir.glob( File.join( File.dirname(__FILE__), '{lib,addons}', 'subfolder', '**', '*.rb' ), &method(:require) )
beseitigt die Abhängigkeit von der Plattform (wie '/' oder '\'). Funktioniert gut. Vielen Dank.
Der beste Weg ist, das Verzeichnis zum require
Ladepfad und dann den Basisnamen jeder Datei hinzuzufügen . Dies liegt daran, dass Sie vermeiden möchten, dass dieselbe Datei versehentlich zweimal benötigt wird - häufig nicht das beabsichtigte Verhalten. Ob eine Datei geladen wird oder nicht, hängt davon ab, ob require
der Pfad zuvor an sie übergeben wurde. Diese einfache irb-Sitzung zeigt beispielsweise, dass Sie fälschlicherweise dieselbe Datei zweimal benötigen und laden können.
$ 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
Beachten Sie, dass die ersten beiden Zeilen zurückgegeben werden, true
was bedeutet, dass dieselbe Datei beide Male geladen wurde. Wenn Pfade verwendet werden, auch wenn die Pfade auf denselben Ort verweisen,require
ist nicht bekannt, dass die Datei bereits erforderlich war.
Hier fügen wir stattdessen dem Ladepfad ein Verzeichnis hinzu und benötigen dann den Basisnamen jeder darin enthaltenen * .rb-Datei.
dir = "/path/to/directory"
$LOAD_PATH.unshift(dir)
Dir[File.join(dir, "*.rb")].each {|file| require File.basename(file) }
Wenn Sie sich nicht darum kümmern, dass die Datei mehr als einmal benötigt wird, oder wenn Sie nur den Inhalt der Datei laden möchten, load
sollten Sie sie möglicherweise anstelle von verwenden require
. Verwenden Sie in diesem Fall load, da es besser ausdrückt, was Sie erreichen möchten. Zum Beispiel:
Dir["/path/to/directory/*.rb"].each {|file| load file }
Anstatt Pfade wie in einigen Antworten zu verketten, verwende ich File.expand_path
:
Dir[File.expand_path('importers/*.rb', File.dirname(__FILE__))].each do |file|
require file
end
Aktualisieren:
Anstatt zu verwenden, können File.dirname
Sie Folgendes tun:
Dir[File.expand_path('../importers/*.rb', __FILE__)].each do |file|
require file
end
Wobei ..
der Dateiname entfernt wird __FILE__
.
File.expand_path
Rails.root.join
Antworten funktionieren auch, wenn Sie in Schienen sind.
In Rails können Sie Folgendes tun:
Dir[Rails.root.join('lib', 'ext', '*.rb')].each { |file| require file }
Update: Korrigiert mit dem Vorschlag von @Jiggneshh Gohel, Schrägstriche zu entfernen.
Rails.root.join('/lib')
generiert beispielsweise keinen korrekten Pfad. Ich fand, dass dieses richtig funktioniert:Dir[Rails.root.join('lib', 'ext', '*.rb')].each { |file| require file }
Und was ist mit : require_relative *Dir['relative path']
?
require_relative *Dir['*.rb']
Arbeit, wenn es nur ein Ruby-Skript gibt. Aber wenn mehrere Ruby-Skripte gefunden werden, erhalten Sierequire_relative': wrong number of arguments (4 for 1) (ArgumentError)