Laut Pickaxe ist die Erweiterung .rb optional. Technisch ändert sich die Bedeutung: "require 'foo.rb'" erfordert foo.rb, während "require 'foo'" möglicherweise foo.rb, foo.so oder foo.dll erfordert.
Sam Stokes
28
Es ist ein subtiles Problem, die Erweiterung nicht zu entfernen. Wenn für einen anderen Teil der Codeaufrufe 'foo' erforderlich ist, lädt Ruby dieselbe Datei erneut, was zu falschen Fehlern führen kann. Ich habe meine eigene Antwort hinzugefügt, die das erklärt und zeigt, wie die Erweiterung entfernt wird.
Dies mag offensichtlich sein, aber es ist erwähnenswert, dass zum Löschen der .rb-Datei auch alle Nicht-.rb-Dateien im Verzeichnis erforderlich sind, was möglicherweise nicht erwünscht ist.
user2398029
10
@ PeteHodgsons Vorschlag ist ungenau. Ruby requireist nicht durch das Vorhandensein oder Fehlen der .rbErweiterung 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).
Sheldonh
345
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):
Sie können auch alle Dir[File.dirname(__FILE__) + '/support/**/*.rb'].each {|file| require file }
untergeordneten
62
Es ist wahrscheinlich sicherer, File.join zu verwenden, als Annahmen über Schrägstriche vorwärts / rückwärts zu treffen:Dir[File.join(File.dirname(__FILE__), 'lib', '*.rb')].each {|file| require file }
Chris
6
Es gibt auch require_relative
maasha
30
Wenn Sie> = Ruby 2.0 verwenden, können Sie __dir__anstelle von verwenden File.dirname(__FILE__).
Christian Bankester
3
@maasha Wie verwenden Sie require_relative, um alle Dateien in einem Verzeichnis zu benötigen?
Ich musste alle meine ActiveRecord-Modelle einbeziehen, das Juwel require_all hat alle Abhängigkeiten herausgefunden und sie perfekt benötigt. Vielen Dank!
Panupan
2
@panupan Beachten Sie jedoch, dass require_alldie 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.
Sheldonh
Es macht keinen Sinn, Ihre App mit Edelsteinen aufzublähen, die Sie einfach durch eine Codezeile ersetzen können. Dies erhöht die Ladezeit Ihrer App und führt langfristig zu mehr Fehlern.
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").
Ist das wirklich der Fall? In der Dokumentation heißt es: Ein Feature wird nicht geladen, wenn sein Name bereits in $ "erscheint. Der Dateiname wird in einen absoluten Pfad konvertiert, daher" erfordert 'a'; require './a' "lädt a.rb nicht zweimal. ruby-doc.org/core/classes/Kernel.html#M001418
Derek
13
Meine Tests zeigen dasselbe, was Derek gesagt hat: require "foo.rb"; require "foo";Wird foo.rbnur einmal geladen .
Rene Saarsoo
@ PeteHodgson- Kannst du das sichern?
Yarin
4
Ruby's requireist nicht durch das Vorhandensein oder Fehlen der .rbErweiterung 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).
Dies ist ein wunderschöner Code. Ich liebe es, wie es keine sichtbaren Blöcke gibt.
Nate Symer
1
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.
Ivan Black
30
Der beste Weg ist, das Verzeichnis zum requireLadepfad 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 requireder 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.
Beachten Sie, dass die ersten beiden Zeilen zurückgegeben werden, truewas 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, loadsollten 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:
Da Rails.rootes sich um eine PathnameInstanz handelt, können Sie dies in jeder Ruby-Umgebung tun, nicht nur in Rails (NB Rails.root.join('lib/ext/*.rb')liest sich etwas
besser
Danke für die Empfehlung; Ich habe bearbeitet, um Ihren Kommentar aufzunehmen.
Dan Kohn
Die Verwendung eines Schrägstrichs (/) für Unterverzeichnisse unter Rails.root 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 }
Jignesh Gohel
@ Jiggneshh Gohel Ich habe Schrägstriche entfernt, wie Sie vorgeschlagen haben, danke.
Dan Kohn
3
Ich bin ein paar Jahre zu spät zur Party, aber ich mag diese einzeilige Lösung, mit der ich Schienen dazu gebracht habe, alles in App / Worker / Anliegen aufzunehmen:
OK, aber in meinem Beispiel ist es nicht. Das '*' ändert die Arität in 1. Es funktioniert als Mehrfachaufruf von require_relative.
Aleksander
1
Das '*' ändert die Arität in 1 - Was meinst du damit? 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)
Antworten:
Wie wäre es mit:
quelle
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):
Bearbeiten: Basierend auf den Kommentaren unten, eine aktualisierte Version:
quelle
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 verwendenFile.dirname(__FILE__)
.require_relative
, um alle Dateien in einem Verzeichnis zu benötigen?Probieren Sie das Juwel require_all aus:
Sie können einfach:
quelle
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.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").
quelle
require "foo.rb"; require "foo";
Wirdfoo.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).oder alternativ, wenn Sie die Dateien in bestimmte Ordner laden möchten:
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.
quelle
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, obrequire
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.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.
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 verwendenrequire
. Verwenden Sie in diesem Fall load, da es besser ausdrückt, was Sie erreichen möchten. Zum Beispiel:quelle
Anstatt Pfade wie in einigen Antworten zu verketten, verwende ich
File.expand_path
:Aktualisieren:
Anstatt zu verwenden, können
File.dirname
Sie Folgendes tun:Wobei
..
der Dateiname entfernt wird__FILE__
.quelle
File.expand_path
Rails.root.join
Antworten funktionieren auch, wenn Sie in Schienen sind.Dies funktioniert rekursiv auf Ihrem lokalen Computer und einer Fernbedienung (wie Heroku), die keine relativen Pfade verwendet.
quelle
In Rails können Sie Folgendes tun:
Update: Korrigiert mit dem Vorschlag von @Jiggneshh Gohel, Schrägstriche zu entfernen.
quelle
Rails.root
es sich um einePathname
Instanz handelt, können Sie dies in jeder Ruby-Umgebung tun, nicht nur in Rails (NBRails.root.join('lib/ext/*.rb')
liest sich etwasRails.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 }
Ich bin ein paar Jahre zu spät zur Party, aber ich mag diese einzeilige Lösung, mit der ich Schienen dazu gebracht habe, alles in App / Worker / Anliegen aufzunehmen:
Dir[ Rails.root.join *%w(app workers concerns *) ].each{ |f| require f }
quelle
Und was ist mit :
require_relative *Dir['relative path']
?quelle
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)