2009-05-07 16 views
79

Ho visto due tecniche comunemente usate per aggiungere la directory del file attualmente in esecuzione a $ LOAD_PATH (o $ :). Vedo i vantaggi di farlo nel caso in cui non stai lavorando con una gemma. Uno sembra più verboso dell'altro, ovviamente, ma c'è una ragione per andare con l'uno sull'altro?

Il primo, il metodo verbose (potrebbe essere eccessivo):

$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) unless $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__))) 

e lo sporco rapido e-più semplice,:

$:.unshift File.dirname(__FILE__) 

Qual è il motivo di andare con uno sopra l'altro?

+1

A ** ** leggermente versione meno prolissa di colui verbose è:. 'File.expand_path (File.dirname (__ FILE __)) {toccare | pwd | $ LOAD_PATH.unshift (pwd) a meno che $ LOAD_PATH.include? (Pwd)} ' –

+0

come si parla della clausola" unless "? Come possono i due sopra essere equivalenti? – inger

+0

Come qualcuno che è venuto qui per cercare di capire come usarlo, è super criptico. Non vedo da dove proviene il nome della directory sugli esempi. Apprezzerei se qualcuno potesse chiarirlo. – SlySherZ

risposta

47

Direi di andare con $:.unshift File.dirname(__FILE__) sull'altro, semplicemente perché ho visto molto più uso di esso in codice rispetto allo $LOAD_PATH uno, ed è anche più corto!

+0

Quando ho iniziato per la prima volta con Ruby, ovviamente pensavo che $ LOAD_PATH fosse migliore. Ma una volta che ti sei laureato da principiante, userei solo $ LOAD_PATH se stavo cercando di rendere il mio codice più leggibile per un principiante. Meh è un trade off. Dipende da quanto è "pubblico" il codice, a patto che l'utilizzo della memoria sia lo stesso per ciascuno, cosa che presumo sia essenzialmente. –

+0

Come controllare se $: contiene già la voce? – inger

+4

Dipende dalla guida di stile che segui per il tuo progetto. La famosa [Guida allo stile di Ruby] (https://github.com/bbatsov/ruby-style-guide#syntax) dice "Evita di utilizzare variabili speciali in stile Perl (come $ :, $ ;, ecc.) abbastanza criptico e il loro uso in tutto tranne gli script one-liner è scoraggiato. " – bobmagoo

18

Non mi piace troppo il modo "veloce e sporco". Chiunque sia nuovo a Ruby starà riflettendo su cosa sia lo $:..

Trovo questo più ovvio.

libdir = File.dirname(__FILE__) 
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir) 

O se mi preoccupo di avere il percorso completo ...

libdir = File.expand_path(File.dirname(__FILE__)) 
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir) 

UPDATE 2009/09/10

Come negli ultimi tempi ho fatto la seguente:

$:.unshift(File.expand_path(File.dirname(__FILE__))) unless 
    $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__))) 

L'ho visto in un sacco di diversi progetti di rubini mentre b Righe di GitHub.

Sembra essere la convention?

+0

@LukeAntins, questo è davvero ottimo ma dove dovrei "bootstrap" load_path nell'applicazione? – gaussblurinc

+0

@gaussblurinc Somewhere 'near the top' del tuo lib/application, ma in realtà dipende. Se tu avessi un file 'bin' che era sempre relativo al tuo' codice' ed è stato sempre eseguito solo dal file 'bin' ... bootstrap nel cestino.Se si dispone di una libreria, quindi il bootstrap in cima al codice della libreria è come in 'lib/code.rb' per accedere a tutto sotto' lib/code/'. Spero che questo diverbio aiuti! –

+0

RuboCop mi informa che '__dir__' può essere usato per ottenere un percorso alla directory del file corrente. – Raphael

136

Il percorso di caricamento Ruby è visto molto comunemente come $:, ma solo perché è corto, non lo rende migliore. Se preferisci la chiarezza all'intelligenza, o se la brevità fine a se stessa ti fa prudere, non devi farlo solo perché tutti gli altri lo sono. Ciao a dire ...

$LOAD_PATH 

... e dire addio a ...

# I don't quite understand what this is doing... 
$: 
+25

Inoltre, Google è molto più difficile per le stringhe come "$:" che contengono solo simboli. – DSimon

+35

@DSimon Non * Google * per '$:', usa http://www.symbolhound.com/ – Sparhawk

7

Se si digita script/console nel progetto Rails e immettere $:, si otterrà un array include tutte le directory necessarie per caricare Ruby. Il take-away di questo piccolo esercizio è che $: è un array. In tal caso, è possibile eseguire le funzioni su di esso come anteporre altre directory al metodo unshift o all'operatore <<. Come hai sottinteso nella tua dichiarazione $: e $LOAD_PATH sono gli stessi.

Lo svantaggio di farlo in modo rapido e sporco come hai detto è questo: se hai già la directory nel tuo percorso di avvio, si ripeterà.

Esempio:

Ho un plugin che ho creato chiamato todo. Il mio elenco è strutturato in questo modo:

 
/---vendor 
    | 
    |---/plugins 
     | 
     |---/todo 
       | 
       |---/lib 
        | 
        |---/app 
          | 
          |---/models 
          |---/controllers 
       | 
       |---/rails 
        | 
        |---init.rb 

Nel file init.rb ho inserito il seguente codice:

## In vendor/plugins/todo/rails/init.rb 
    %w{ models controllers models }.each do |dir| 
     path = File.expand_path(File.join(File.dirname(__FILE__), '../lib', 'app', dir)) 
     $LOAD_PATH << path 
     ActiveSupport::Dependencies.load_paths << path 
     ActiveSupport::Dependencies.load_once_paths.delete(path) 
    end 

noti come dico il blocco di codice per eseguire le azioni all'interno del blocco alle corde 'modelli', 'controller' e 'modelli', dove ripeto 'modelli'. (FYI, %w{ ... } è solo un altro modo per dire a Ruby di tenere una serie di stringhe). Quando eseguo script/console, digito il seguente:

>> puts $: 

E ho questo tipo in modo che sia più facile da leggere il contenuto della stringa. L'output che ottengo è:

 
... 
... 
./Users/Me/mySites/myRailsApp/vendor/plugins/todo/lib/app/models 
./Users/Me/mySites/myRailsApp/vendor/plugins/todo/lib/app/controllers 
./Users/Me/mySites/myRailsApp/vendor/plugins/todo/lib/app/models 

Come si può vedere, anche se questo è il più semplice esempio ho potuto creare durante l'utilizzo di un progetto che sto attualmente lavorando su, se non stai attento il modo rapido e sporco porterà a percorsi ripetuti. Il modo più lungo controllerà i percorsi ripetuti e si assicurerà che non si verifichino.

Se sei un programmatore esperto di Rails, probabilmente hai una buona idea di quello che stai facendo e probabilmente non commetti l'errore di ripetere percorsi. Se sei un principiante, andrei con il lungo cammino finché non capirai davvero cosa stai facendo.

+0

la tua risposta molto utile e anche ben spiegata. Modifica consigliata: il metodo 'load_paths' e' load_once_paths.delete' sono stati deprecati. Sarebbe utile aggiornare le righe che si riferiscono a loro come: 'ActiveSupport :: Dependencies.autoload_paths << percorso' ' ActiveSupport :: Dependencies.autoload_once_paths.delete (path) ' – Uzzar

4

migliore che ho incontrato per l'aggiunta di una directory tramite percorso relativo quando si utilizza Rspec. Lo trovo abbastanza prolisso ma anche un bel transatlantico.

$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))