Was ist der Unterschied zwischen require_relative und require in Ruby?

302

Was ist der Unterschied zwischen require_relativeund requirein Ruby?

agentbanks217
quelle
9
Vor 1.9.2 war require_relative nicht erforderlich, da sich das aktuelle Skriptverzeichnis in befand $:. Siehe stackoverflow.com/questions/2900370
Nakilon
1
require_relative erfordert eine Datei, die speziell auf die Datei verweist, die sie aufruft. require erfordert eine Datei, die im $ LOAD_PATH enthalten ist.
Donato
nützlicher Artikel über Unterschiede => medium.com/@ellishim/…
ahmed hamdy

Antworten:

298

Schauen Sie sich einfach die Dokumente an :

require_relativeergänzt die integrierte Methode, requireindem Sie eine Datei laden können, die relativ zu der Datei ist, die die require_relativeAnweisung enthält.

Wenn Sie beispielsweise Unit-Test-Klassen im Verzeichnis "test" und Daten für diese im Verzeichnis "test / data" des Tests haben, können Sie in einem Testfall eine Zeile wie diese verwenden:

require_relative "data/customer_data_1"
miku
quelle
28
Gibt es einen Unterschied zwischen require './file.rb'und require_relative 'file.rb'?
Ciro Santilli 法轮功 冠状 病 六四 事件 25
69
@CiroSantilli Ja. require_relativeMit dieser Option können Sie "eine Datei laden, die relativ zu der Datei ist, die die require_relativeAnweisung enthält ". Mit require, ./zeigt einen Weg, der zu Ihrem aktuellen Arbeitsverzeichnis ist relativ.
Ajedi32
16
Ich denke, es ist wichtiger zu beachten, dass require strimmer Verzeichnisse in $ LOAD_PATH durchsucht werden. Sie sollten verwenden, require_relativewenn die zu ladende Datei irgendwo relativ zu der Datei vorhanden ist, die das Laden erfordert. Reserve requirefür "externe" Abhängigkeiten.
Rthbound
97

require_relative ist eine bequeme Teilmenge von require

require_relative('path')

gleich:

require(File.expand_path('path', File.dirname(__FILE__)))

wenn __FILE__definiert ist, oder es wird LoadErroranders ausgelöst .

Dies impliziert Folgendes:

  • require_relative 'a'und require_relative './a'erfordern relativ zur aktuellen Datei ( __FILE__).

    Dies ist das, was Sie verwenden möchten, wenn Sie es in Ihrer Bibliothek benötigen, da das Ergebnis nicht vom aktuellen Verzeichnis des Anrufers abhängen soll.

  • eval('require_relative("a.rb")')erhöht, LoadErrorweil __FILE__nicht im Inneren definiert ist eval.

    Aus diesem Grund können Sie keine require_relativeRSpec-Tests verwenden, die bearbeitet werden eval.

Folgende Operationen sind nur möglich mit require:

  • require './a.rb'erfordert relativ zum aktuellen Verzeichnis

  • require 'a.rb'verwendet den Suchpfad ( $LOAD_PATH), um zu erfordern. Es werden keine Dateien relativ zum aktuellen Verzeichnis oder Pfad gefunden.

    Dies ist nicht möglich, require_relativeda in den Dokumenten angegeben ist, dass die Pfadsuche nur dann erfolgt, wenn "der Dateiname nicht in einen absoluten Pfad aufgelöst wird" (dh mit /oder ./oder beginnt ../), was immer der Fall ist File.expand_path.

Der folgende Vorgang ist mit beiden möglich, Sie sollten ihn jedoch verwenden, requireda er kürzer und effizienter ist:

  • require '/a.rb'und require_relative '/a.rb'beide erfordern den absoluten Pfad.

Quelle lesen

Wenn die Dokumente nicht klar sind, empfehle ich Ihnen, einen Blick auf die Quellen zu werfen (Quelle in den Dokumenten umschalten). In einigen Fällen hilft es zu verstehen, was los ist.

benötigen:

VALUE rb_f_require(VALUE obj, VALUE fname) {
  return rb_require_safe(fname, rb_safe_level());
}

require_relative:

VALUE rb_f_require_relative(VALUE obj, VALUE fname) {
    VALUE base = rb_current_realfilepath();
    if (NIL_P(base)) {
        rb_loaderror("cannot infer basepath");
    }
    base = rb_file_dirname(base);
    return rb_require_safe(rb_file_absolute_path(fname, base), rb_safe_level());
}

Daraus können wir schließen

require_relative('path')

ist das gleiche wie:

require(File.expand_path('path', File.dirname(__FILE__)))

weil:

rb_file_absolute_path   =~ File.expand_path
rb_file_dirname1        =~ File.dirname
rb_current_realfilepath =~ __FILE__
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
quelle
74

Von der Ruby-API :

require_relative ergänzt die integrierte Methode require, indem Sie eine Datei laden können, die relativ zu der Datei ist, die die Anweisung require_relative enthält.

Wenn Sie zum Laden einer Datei require verwenden, greifen Sie normalerweise auf Funktionen zu, die ordnungsgemäß in Ihrem System installiert und zugänglich gemacht wurden. require bietet keine gute Lösung zum Laden von Dateien im Projektcode. Dies kann während einer Entwicklungsphase nützlich sein, um auf Testdaten zuzugreifen oder sogar um auf Dateien zuzugreifen, die innerhalb eines Projekts "gesperrt" sind und nicht für den externen Gebrauch bestimmt sind.

Wenn Sie beispielsweise Unit-Test-Klassen im Verzeichnis "test" und Daten für diese im Verzeichnis "test / data" des Tests haben, können Sie in einem Testfall eine Zeile wie diese verwenden:

require_relative "data/customer_data_1" 

Da sich wahrscheinlich weder "Test" noch "Test / Daten" in Rubys Bibliothekspfad befinden (und das aus gutem Grund), werden sie von einer normalen Anforderung nicht gefunden. require_relative ist eine gute Lösung für dieses spezielle Problem.

Sie können die Erweiterung (.rb oder .so) der Datei, die Sie laden, einschließen oder weglassen.

Pfad muss auf to_str antworten.

Die Dokumentation finden Sie unter http://extensions.rubyforge.org/rdoc/classes/Kernel.html

svilenv
quelle
50

Zusammenfassung

Verwenden Sie requirefür installierte Edelsteine

Verwendung require_relativefür lokale Dateien

requireverwendet Ihre $LOAD_PATH, um die Dateien zu finden.
require_relativeVerwendet den aktuellen Speicherort der Datei mithilfe der Anweisung


benötigen

Require setzt voraus, dass Sie (z. B. gem install [package]) irgendwo auf Ihrem System ein Paket für diese Funktionalität installiert haben .

Bei Verwendung requireSie können die „Verwendung ./“ Format für eine Datei im aktuellen Verzeichnis, zum Beispiel , require "./my_file"aber das ist nicht eine gemeinsame oder empfohlene Praxis und Sie sollten verwenden require_relativestatt.

require_relative

Dies bedeutet einfach, die Datei 'relativ zum Speicherort der Datei mit der Anweisung require_relative' einzuschließen. Ich empfehle generell , dass sich Dateien "innerhalb" des aktuellen Verzeichnisbaums befinden und nicht "up", z. B. nicht verwenden

require_relative '../../../filename'

(bis zu 3 Verzeichnisebenen) innerhalb des Dateisystems, da dies zu unnötigen und spröden Abhängigkeiten führt. In einigen Fällen kann jedoch ein weiterer Verzeichnisbaumzweig erforderlich sein, wenn Sie sich bereits in einem Verzeichnisbaum befinden. Einfacher gesagt, verwenden Sie require_relative möglicherweise nicht für Dateien außerhalb dieses Repositorys (vorausgesetzt, Sie verwenden git, das zu diesem Zeitpunkt Ende 2018 weitgehend ein De-facto-Standard ist).

Beachten Sie, dass require_relativedas aktuelle Verzeichnis der Datei mit der Anweisung require_relative verwendet wird (also nicht unbedingt Ihr aktuelles Verzeichnis, aus dem Sie den Befehl verwenden). Dies hält den require_relativePfad "stabil", da er immer relativ zu der Datei ist, die ihn auf die gleiche Weise benötigt.

Michael Durrant
quelle
27

Die besten Antworten sind richtig, aber zutiefst technisch. Für diejenigen, die neu bei Ruby sind:

  • require_relative wird höchstwahrscheinlich verwendet, um Code aus einer anderen Datei einzubringen, die Sie geschrieben haben.

Was ist zum Beispiel, wenn Sie Daten haben ~/my-project/data.rbund diese einschließen möchten ~/my-project/solution.rb? in solution.rbwürden Sie hinzufügen require_relative 'data'.

Es ist wichtig zu beachten, dass sich diese Dateien nicht im selben Verzeichnis befinden müssen. require_relative '../../folder1/folder2/data'ist auch gültig.

  • require wird höchstwahrscheinlich verwendet, um Code aus einer Bibliothek einzubringen, die jemand anderes geschrieben hat.

Was ist beispielsweise, wenn Sie eine der in der active_supportBibliothek bereitgestellten Hilfsfunktionen verwenden möchten ? Sie müssen das Juwel mit gem install activesupportund dann in der Datei installieren require 'active_support'.

require 'active_support/all'
"FooBar".underscore

Anders gesagt ...

  • require_relative erfordert eine Datei, die speziell auf die Datei verweist, die sie aufruft.

  • requireerfordert eine Datei in der $LOAD_PATH.

Common-Nighthawk
quelle
3
Wie kann ich diese Antwort abstimmen und ganz nach oben bringen, damit jeder Besucher dieser Fragenseite sofort eine klare und verständliche Antwort erhält, ohne sich den Kopf zu zerbrechen?
TiredOfProgramming
16

Ich habe gerade gesehen, dass der RSpec-Code einen Kommentar dazu enthält, require_relativedass O (1) konstant und requireO (N) linear ist. Der Unterschied ist also wahrscheinlich, dass dies require_relativeder bevorzugte ist require.

mech
quelle
1
Interessant. Ich bin hier gelandet und habe nach Informationen zu einem Geschwindigkeitsvergleich gesucht. Meiner require_relativeMeinung nach war das schneller, weil der Loader den Ladepfad bei der Suche nach der Datei nicht durchlaufen muss. Im Wesentlichen require_relativebietet eine direkte Verbindung.
Clint Pachl
Frühe Diskussion über die erforderliche Geschwindigkeit und das RSpec- Änderungsprotokoll .
Clint Pachl
1

Ich möchte hinzufügen, dass Sie unter Windows verwenden können, require './1.rb'wenn das Skript lokal oder von einem zugeordneten Netzwerklaufwerk ausgeführt wird, aber wenn Sie von einem UNC- \\servername\sharename\folderPfad ausgeführt werden, den Sie verwenden müssen require_relative './1.rb'.

Ich mische mich nicht in die Diskussion, die ich aus anderen Gründen verwenden soll.

Peter
quelle
Ich wollte wissen, wie Sie die require_relativeDatei laden Könnten Sie bitte eine Idee auf diese stackoverflow.com/questions/43487784/…
Emjey