Qual'è la differenza tra require_relative
e require
in Ruby?
Qual'è la differenza tra require_relative
e require
in Ruby?
Risposte:
Guarda i documenti :
require_relative
integra il metodo incorporatorequire
consentendo di caricare un file relativo al file contenente l'require_relative
istruzione.Ad esempio, se si hanno classi di unit test nella directory "test" e dati per esse nella directory "test / data" del test, è possibile utilizzare una riga come questa in un caso di test:
require_relative "data/customer_data_1"
require './file.rb'
e require_relative 'file.rb'
?
require_relative
consente di "caricare un file relativo al file contenente l' require_relative
istruzione ". Con require
, ./
indica un percorso relativo alla directory di lavoro corrente.
require str
cercherà sempre tra le directory in $ LOAD_PATH. È necessario utilizzare require_relative
quando il file che è necessario caricare esiste da qualche parte rispetto al file che richiede il caricamento. Riserva require
per dipendenze "esterne".
require_relative
è un sottoinsieme conveniente di require
require_relative('path')
è uguale a:
require(File.expand_path('path', File.dirname(__FILE__)))
se __FILE__
è definito o genera LoadError
diversamente.
Questo implica che:
require_relative 'a'
e require_relative './a'
richiede relativamente al file corrente ( __FILE__
).
Questo è ciò che si desidera utilizzare quando richiesto all'interno della libreria, poiché non si desidera che il risultato dipenda dalla directory corrente del chiamante.
eval('require_relative("a.rb")')
aumenta LoadError
perché __FILE__
non è definito all'interno eval
.
Questo è il motivo per cui non è possibile utilizzare require_relative
nei test RSpec, che vengono modificati eval
.
Le seguenti operazioni sono possibili solo con require
:
require './a.rb'
richiede rispetto alla directory corrente
require 'a.rb'
utilizza il percorso di ricerca ( $LOAD_PATH
) per richiedere. Non trova i file relativi alla directory o al percorso correnti.
Questo non è possibile require_relative
perché i documenti affermano che la ricerca del percorso avviene solo quando "il nome del file non si risolve in un percorso assoluto" (cioè inizia con /
o ./
o ../
), il che è sempre il caso File.expand_path
.
La seguente operazione è possibile con entrambi, ma è consigliabile utilizzarla require
poiché è più breve ed efficiente:
require '/a.rb'
ed require_relative '/a.rb'
entrambi richiedono il percorso assoluto.Lettura della fonte
Quando i documenti non sono chiari, ti consiglio di dare un'occhiata alle fonti (attiva / disattiva la fonte nei documenti). In alcuni casi, aiuta a capire cosa sta succedendo.
richiedono:
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());
}
Questo ci consente di concludere ciò
require_relative('path')
equivale a:
require(File.expand_path('path', File.dirname(__FILE__)))
perché:
rb_file_absolute_path =~ File.expand_path
rb_file_dirname1 =~ File.dirname
rb_current_realfilepath =~ __FILE__
Dall'API Ruby :
Require_relative integra il metodo incorporato richiesto consentendo di caricare un file relativo al file contenente l'istruzione request_relative.
Quando si utilizza è necessario caricare un file, di solito si accede a funzionalità che sono state installate correttamente e rese accessibili nel proprio sistema. request non offre una buona soluzione per il caricamento di file all'interno del codice del progetto. Ciò può essere utile durante una fase di sviluppo, per l'accesso ai dati di test o anche per l'accesso a file "bloccati" all'interno di un progetto, non destinati all'uso esterno.
Ad esempio, se si hanno classi di unit test nella directory "test" e dati per esse nella directory "test / data" del test, è possibile utilizzare una riga come questa in un caso di test:
require_relative "data/customer_data_1"
Dal momento che né "test" né "test / dati" sono probabilmente nel percorso della libreria di Ruby (e per una buona ragione), un normale requisito non li troverà. require_relative è una buona soluzione per questo particolare problema.
È possibile includere o omettere l'estensione (.rb o .so) del file che si sta caricando.
il percorso deve rispondere a to_str.
Puoi trovare la documentazione su http://extensions.rubyforge.org/rdoc/classes/Kernel.html
require
per gemme installaterequire_relative
per file localirequire
usa il tuo $LOAD_PATH
per trovare i file.
require_relative
utilizza la posizione corrente del file usando l'istruzione
Require si basa sul fatto che tu abbia installato (ad esempio gem install [package]
) un pacchetto da qualche parte sul tuo sistema per quella funzionalità.
Quando si utilizza require
è possibile utilizzare il ./
formato " " per un file nella directory corrente, ad esempio, require "./my_file"
ma questa non è una pratica comune o consigliata e si dovrebbe usare require_relative
invece.
Questo significa semplicemente includere il file 'relativo alla posizione del file con l'istruzione request_relative'. In genere raccomando che i file siano "all'interno" della struttura di directory corrente anziché "su", ad esempio non utilizzare
require_relative '../../../filename'
(fino a 3 livelli di directory) all'interno del file system perché tende a creare dipendenze inutili e fragili. Tuttavia, in alcuni casi, se si è già "in profondità" all'interno di un albero di directory, potrebbe essere necessario "su e giù" un altro ramo dell'albero di directory. Più semplicemente, forse, non utilizzare request_relative per i file al di fuori di questo repository (supponendo che tu stia usando git che è in gran parte uno standard di fatto a questo punto, alla fine del 2018).
Si noti che require_relative
utilizza la directory corrente del file con l' istruzione request_relative (quindi non necessariamente la directory corrente da cui si sta utilizzando il comando). Ciò mantiene il require_relative
percorso "stabile" in quanto è sempre relativo al file che lo richiede allo stesso modo.
Le risposte migliori sono corrette, ma profondamente tecniche. Per quelli più recenti di Ruby:
require_relative
molto probabilmente verrà utilizzato per inserire il codice da un altro file che hai scritto. per esempio, cosa succede se si dispone di dati ~/my-project/data.rb
e si desidera includerli in ~/my-project/solution.rb
? in solution.rb
te aggiungeresti require_relative 'data'
.
è importante notare che questi file non devono trovarsi nella stessa directory. require_relative '../../folder1/folder2/data'
è anche valido.
require
molto probabilmente verrà utilizzato per inserire codice da una libreria scritta da qualcun altro.per esempio, cosa succede se si desidera utilizzare una delle funzioni di supporto fornite nella active_support
libreria? dovrai installare la gemma con gem install activesupport
e poi nel file require 'active_support'
.
require 'active_support/all'
"FooBar".underscore
Detto diversamente:
require_relative
richiede un file specificamente indicato rispetto al file che lo chiama.
require
richiede un file incluso in $LOAD_PATH
.
Ho appena visto che il codice di RSpec ha dei commenti require_relative
sull'essere costante O (1) e require
lineare O (N). Quindi probabilmente la differenza è che require_relative
è quella preferita di require
.
require_relative
fosse più veloce perché il caricatore non deve attraversare il percorso di caricamento nella ricerca del file. In sostanza, require_relative
fornisce un collegamento diretto.
Voglio aggiungere che quando si utilizza Windows è possibile utilizzare require './1.rb'
se lo script viene eseguito localmente o da un'unità di rete mappata ma quando eseguito da un \\servername\sharename\folder
percorso UNC è necessario utilizzare require_relative './1.rb'
.
Non mi confondo nella discussione che utilizzare per altri motivi.
require_relative
file di La prego di lanciare un'idea a questo stackoverflow.com/questions/43487784/...
$:
. Vedere stackoverflow.com/questions/2900370