Qual'è la differenza tra require_relative e require in Ruby?


302

Qual'è la differenza tra require_relativee requirein Ruby?


9
Prima della 1.9.2 non c'era bisogno di require_relative, perché la directory corrente dello script era in $:. Vedere stackoverflow.com/questions/2900370
Nakilon

1
require_relative richiede un file specificamente indicato come relativo al file che lo chiama. richiede richiede un file incluso in $ LOAD_PATH.
Donato,

articolo utile sulle differenze => medium.com/@ellishim/…
ahmed hamdy

Risposte:


298

Guarda i documenti :

require_relativeintegra il metodo incorporato requireconsentendo di caricare un file relativo al file contenente l' require_relativeistruzione.

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"

28
C'è una differenza tra require './file.rb'e require_relative 'file.rb'?
Ciro Santilli 25 冠状 病 六四 事件 法轮功

69
@CiroSantilli Sì. require_relativeconsente di "caricare un file relativo al file contenente l' require_relativeistruzione ". Con require, ./indica un percorso relativo alla directory di lavoro corrente.
Ajedi32

17
Penso che sia più importante notare che require strcercherà sempre tra le directory in $ LOAD_PATH. È necessario utilizzare require_relativequando il file che è necessario caricare esiste da qualche parte rispetto al file che richiede il caricamento. Riserva requireper dipendenze "esterne".
uscita il

97

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 LoadErrordiversamente.

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 LoadErrorperché __FILE__non è definito all'interno eval.

    Questo è il motivo per cui non è possibile utilizzare require_relativenei 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_relativeperché 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 requirepoiché è 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__

74

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


50

Sommario

Utilizzare requireper gemme installate

Utilizzare require_relativeper file locali

requireusa il tuo $LOAD_PATHper trovare i file.
require_relativeutilizza la posizione corrente del file usando l'istruzione


richiedere

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_relativeinvece.

require_relative

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_relativeutilizza 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_relativepercorso "stabile" in quanto è sempre relativo al file che lo richiede allo stesso modo.


27

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.rbe si desidera includerli in ~/my-project/solution.rb? in solution.rbte 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_supportlibreria? dovrai installare la gemma con gem install activesupporte 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.

  • requirerichiede un file incluso in $LOAD_PATH.


3
Come posso votare questa risposta e portarla fino in cima, così ogni visitatore di questa pagina di domande otterrà subito una risposta chiara e comprensibile senza rompere il cervello?
Stanco di programmare l'

16

Ho appena visto che il codice di RSpec ha dei commenti require_relativesull'essere costante O (1) e requirelineare O (N). Quindi probabilmente la differenza è che require_relativeè quella preferita di require.


1
Interessante. Sono atterrato qui alla ricerca di informazioni su un confronto di velocità. Pensavo che require_relativefosse più veloce perché il caricatore non deve attraversare il percorso di caricamento nella ricerca del file. In sostanza, require_relativefornisce un collegamento diretto.
Clint Pachl,

Disscussion presto circa la velocità require_relative e RSpec changelog .
Clint Pachl,

1

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\folderpercorso UNC è necessario utilizzare require_relative './1.rb'.

Non mi confondo nella discussione che utilizzare per altri motivi.


Volevo sapere come si fa a caricare il require_relativefile di La prego di lanciare un'idea a questo stackoverflow.com/questions/43487784/...
Emjey
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.