Gibt es einen großen Unterschied zwischen load
und require
in den Ruby on Rails-Anwendungen? Oder haben beide die gleiche Funktionalität?
ruby-on-rails
ruby
Arpit Vaishnav
quelle
quelle
require
,load
oderautoload
in Ruby?Antworten:
require
Sucht in allen definierten Suchpfaden nach der Bibliothek und hängt auch .rb oder .so an den von Ihnen eingegebenen Dateinamen an. Außerdem wird sichergestellt, dass eine Bibliothek nur einmal enthalten ist. Wenn Ihre Anwendung also Bibliothek A und B benötigt und Bibliothek B auch Bibliothek A benötigt, wird A nur einmal geladen.Mit
load
müssen Sie den vollständigen Namen der Bibliothek hinzufügen und sie wird bei jedem Aufruf geladenload
- auch wenn sie sich bereits im Speicher befindet.quelle
require
Verfolgt, was bereits über das globale Array$LOADED_FEATURES
($"
) geladen wurde , dasload
ignoriert wird.Ein weiterer Unterschied zwischen
Kernel#require
undKernel#load
besteht darin, dassKernel#load
ein optionales zweites Argument verwendet wird, mit dem Sie den geladenen Code in ein anonymes leeres Modul einschließen können.Leider ist es nicht sehr nützlich. Erstens ist es für den
load
ed-Code einfach , aus dem Modul auszubrechen, indem er einfach auf den globalen Namespace zugreift, dh er kann immer noch so etwas wie Monkeypatch ausführenclass ::String; def foo; end end
. Und zweitens wirdload
das Modul, in das der Code eingeschlossen ist , nicht zurückgegeben, sodass Sie ihn grundsätzlichObjectSpace::each_object(Module)
von Hand herausfischen müssen .quelle
Kernel#load
hatte ein anderes Argumentload
ed-Code einfach , aus dem Modul auszubrechen, indem er einfach auf den globalen Namespace zugreift, dh er kann immer noch so etwas wie Monkeypatch ausführenclass ::String; def foo; end end
. Und zweitens wirdload
das Modul, in das der Code eingeschlossen ist , nicht zurückgegeben, sodass Sie ihn grundsätzlichObjectSpace::each_object(Module)
von Hand herausfischen müssen .Ich habe eine Rails-Anwendung ausgeführt und in Gemfile einen bestimmten benutzerdefinierten Edelstein mit der Option "require: false" erstellt. Als ich nun den Rails-Server oder die Rails-Konsole geladen habe, konnte ich den Gem im Initialisierer anfordern und der Gem wurde geladen. Als ich jedoch einen Spezifikationstest mit rspec und capybara durchführte, wurde ein Ladefehler angezeigt. Und ich war völlig verwirrt, warum der Edelstein beim Ausführen eines Tests nicht in $ LOAD_PATH gefunden wurde.
Also habe ich all die verschiedenen Arten der Interaktion von Laden, Erfordernis, Rubygems und Bundler überprüft. Und dies ist eine Zusammenfassung meiner Ergebnisse, die mir geholfen haben, die Lösung für mein spezielles Problem zu finden:
Belastung
1) Sie können einen absoluten Pfad zu einer Ruby-Datei übergeben und der Code in dieser Datei wird ausgeführt.
2) Sie können einen relativen Pfad zum Laden übergeben. Wenn Sie sich im selben Verzeichnis wie die Datei befinden, wird sie gefunden:
Wenn Sie jedoch versuchen, eine Datei mit load () aus einem anderen Verzeichnis zu laden, wird sie nicht mit einem relativen Pfad gefunden, der auf dem aktuellen Arbeitsverzeichnis basiert (z. B. ./):
3) Wie oben gezeigt, gibt load immer true zurück (wenn die Datei nicht geladen werden konnte, wird a ausgelöst
LoadError
).4) Globale Variablen, Klassen, Konstanten und Methoden werden importiert, jedoch keine lokalen Variablen.
5) Wenn Sie zweimal die gleiche Datei laden, wird der Code in dieser Datei zweimal ausgeführt. Wenn die angegebene Datei eine Konstante definiert, wird diese Konstante zweimal definiert, wodurch eine Warnung ausgegeben wird.
6) $ LOAD_PATH ist ein Array von absoluten Pfaden. Wenn Sie nur einen Dateinamen laden, durchläuft er $ LOAD_PATH und sucht in jedem Verzeichnis nach der Datei.
benötigen
1) Wenn Sie dieselbe Datei zweimal aufrufen müssen, wird sie nur einmal ausgeführt. Es ist auch klug genug, dieselbe Datei nicht zweimal zu laden, wenn Sie einmal mit einem relativen Pfad und einmal mit einem absoluten Pfad darauf verweisen.
2) Rückgabe true erforderlich, wenn die Datei ausgeführt wurde, und false, wenn dies nicht der Fall war.
3) require verfolgt, welche Dateien bereits in die globale Variable $ LOADED_FEATURES geladen wurden.
4) Sie müssen die Dateierweiterung nicht angeben:
5) require sucht nach foo.rb, aber auch nach dynamischen Bibliotheksdateien wie foo.so, foo.o oder foo.dll. So können Sie C-Code von Ruby aus aufrufen.
6) require überprüft das aktuelle Verzeichnis nicht, da sich das aktuelle Verzeichnis standardmäßig nicht in $ LOAD_PATH befindet.
7) require_relative nimmt einen Pfad relativ zur aktuellen Datei, nicht zum Arbeitsverzeichnis des Prozesses.
Rubygems
1) Rubygems ist ein Paketmanager, mit dem die Installation von Ruby-Bibliotheken namens Gems einfach verwaltet werden kann.
2) Der Inhalt wird als Zip-Datei verpackt, die eine Reihe von Ruby-Dateien und / oder dynamischen Bibliotheksdateien enthält, die von Ihrem Code zusammen mit einigen Metadaten importiert werden können.
3) Rubygems ersetzt die Standardmethode require durch eine eigene Version. Diese Version durchsucht zusätzlich zu den Verzeichnissen in $ LOAD_PATH Ihre installierten Edelsteine. Wenn Rubygems die Datei in Ihren Edelsteinen findet, wird dieser Edelstein Ihrem $ LOAD_PATH hinzugefügt.
4) Der Befehl gem install ermittelt alle Abhängigkeiten eines Gems und installiert sie. Tatsächlich werden alle Abhängigkeiten eines Edelsteins installiert, bevor der Edelstein selbst installiert wird.
Bundler
1) Mit Bundler können Sie alle Edelsteine angeben, die Ihr Projekt benötigt, und optional welche Versionen dieser Edelsteine. Dann installiert der Befehl bundle alle diese Edelsteine und ihre Abhängigkeiten.
2) Sie geben in einer Datei namens Gemfile an, welche Edelsteine Sie benötigen.
3) Der Befehl bundle installiert auch alle in Gemfile.lock aufgelisteten Edelsteine in den angegebenen spezifischen Versionen.
4) Wenn Sie bundle exec vor einen Befehl stellen, z. B. bundle exec rspec, wird sichergestellt, dass require die in Ihrer Gemfile.lock angegebene Version eines Gems lädt.
Schienen und Bundler
1) In config / boot.rb muss 'bundler / setup' ausgeführt werden. Bundler stellt sicher, dass Ruby alle Edelsteine in der Gemfile (und alle ihre Abhängigkeiten) finden kann. require 'bundler / setup' erkennt automatisch Ihre Gemfile und stellt Ruby alle Gems in Ihrer Gemfile zur Verfügung (technisch gesehen werden die Gems "auf den Ladepfad" gesetzt). Sie können sich das als Hinzufügen einiger zusätzlicher Kräfte vorstellen, um 'Rubygems' zu benötigen.
2) Nachdem Ihr Code Ruby zur Verfügung steht, können Sie die Edelsteine benötigen, die Sie benötigen. Zum Beispiel können Sie "Sinatra" benötigen. Wenn Sie viele Abhängigkeiten haben, möchten Sie vielleicht sagen, dass Sie alle Edelsteine in meiner Gem-Datei benötigen. Geben Sie dazu den folgenden Code ein, der unmittelbar nach "bundler / setup" erforderlich ist:
3) Für den Aufruf von Bundler.require ist standardmäßig jeder Edelstein in Ihrer Gemfile erforderlich. Wenn in der Zeile in der Gem-Datei gem 'foo' steht: require => false, wird sichergestellt, dass foo installiert ist, aber nicht require aufgerufen. Sie müssen require ('foo') anrufen, wenn Sie den Edelstein verwenden möchten.
Angesichts dieser Wissensbreite kehrte ich zum Thema meines Tests zurück und stellte fest, dass ich den Edelstein in rails_helper.rb explizit benötigen musste, da Bundler.setup ihn zu $ LOAD_PATH hinzufügte, aber Folgendes erforderte: false schloss Bundler.require aus, ihn explizit zu benötigen . Und dann wurde das Problem behoben.
quelle