Perché Ruby 1.9.2 rimuove "." da LOAD_PATH e qual è l'alternativa?


154

Le ultime modifiche apportate a Ruby 1.9.2 non rendono più la directory corrente .parte del tuo LOAD_PATH. Ho un numero non banale di Rakefile che presumono che faccia .parte del LOAD_PATH, quindi questo li ha spezzati (hanno riferito "nessun file da caricare" per tutte le istruzioni che si basano sul percorso del progetto). C'era una giustificazione particolare per farlo?

Per quanto riguarda una correzione, l'aggiunta $: << "."ovunque funziona, ma sembra incredibilmente confusa e non voglio farlo. Qual è il modo preferito per rendere compatibili i miei Rakefiles 1.9.2+?

Risposte:


141

Era considerato un rischio di "sicurezza".

Puoi aggirarlo usando percorsi assoluti

File.expand_path(__FILE__) et al

o facendo

require './filename' (ironically).

o usando

require_relative 'filename'

o aggiungendo una directory "include"

ruby -I . ...

o lo stesso, usando irb;

$irb -I .

27
Ho finito per usare require_relative. Grazie.
John Feminella,

11
È simile alla maggior parte degli unix che non include la directory corrente nel percorso per l'esecuzione degli eseguibili?
Andrew Grimm,

5
require './filename'funziona solo se lo script viene eseguito con la directory di lavoro impostata sulla stessa directory in cui risiede lo script. Questo non è spesso il caso di progetti multi-directory.
mxcl

34

Ci sono due ragioni:

  • robustezza e
  • sicurezza

Entrambi si basano sullo stesso principio di base: in generale, semplicemente non si può sapere quale sia la directory corrente, quando viene eseguito il codice. Ciò significa che, quando si richiede un file e si dipende dal fatto che si trovi nella directory corrente, non si ha modo di controllare se quel file sarà presente o se si tratta del file che ci si aspetta che sia effettivamente presente.


5
Non penso che imporre che due file si trovino nella stessa posizione l'uno rispetto all'altro sia necessariamente un cattivo requisito. Se ciò fosse vero, non avremmo alcuna utilità per le directory.
John Feminella,

4
@John Feminella: cosa c'entra questo con l'inserimento di file in percorsi l'uno rispetto all'altro? La domanda è di metterli relativi a ., cioè l'attuale directory di lavoro. Se l'utente si trova cdin una directory diversa, la directory di lavoro corrente cambia e ora i file sono require completamente diversi a seconda della directory in cui si trovava l'utente quando ha chiamato lo script. Non penso sia una buona idea.
Jörg W Mittag,

Quindi, per mantenere un'interfaccia decente, dovresti farlo? $: << File.dirname(__FILE__)
Joshua Cheek,

4
@Joshua Cheek: Personalmente, non mi piace. (Ma per favore non guardare il mio vecchio codice, perché è pieno di quel tipo di cose :-)). Faccio semplicemente finta che la libdirectory si trova su $LOAD_PATHe quindi su requiretutti i file relativi a lib. In altre parole: lascio all'amministratore capire come impostare $LOAD_PATHcorrettamente. Se usi RubyGems, è banale, perché RubyGems lo fa automaticamente per te, e se usi i pacchetti Debian, allora è il compito del manutentore del pacchetto. Tutto sommato, sembra funzionare abbastanza bene.
Jörg W Mittag,

8
@Joshua Guancia: Inoltre, come una sorta-di contrappeso alla rimozione .da $LOAD_PATH, Ruby 1.9.2 introduce require_relativeche ... sorpresa ... requiresa file relativo alla posizione del file attualmente in esecuzione (cioè rispetto al File.dirname(__FILE__)).
Jörg W Mittag,

16

Come sottolineato da altre risposte, è un rischio per la sicurezza perché .nel percorso di caricamento fa riferimento alla directory di lavoro Dir.pwdcorrente, non alla directory del file corrente che viene caricata. Quindi chiunque stia eseguendo il tuo script può cambiarlo semplicemente cdinserendo un'altra directory. Non bene!

Ho usato percorsi completi costruiti __FILE__in alternativa.

require File.expand_path(File.join(File.dirname(__FILE__), 'filename'))

A differenza di require_relativequesto, è retrocompatibile con Ruby 1.8.7.


4
C'è anche questa variazione (che trovo personalmente più leggibile): require Pathname.new(__FILE__).dirname + 'filename'
Tyler Rick,

8

Uso require_relative 'file_to_require'

Inseriscilo nel tuo codice per far funzionare requ_relative in 1.8.7:

unless Kernel.respond_to?(:require_relative)
  module Kernel
    def require_relative(path)
      require File.join(File.dirname(caller.first), path.to_str)
    end
  end
end


3

Ho scoperto che questo è un cambiamento confuso fino a quando ho realizzato un paio di cose.

Puoi impostare RUBYLIB nel tuo .profile (Unix) e continuare la vita come facevi prima:

export RUBYLIB="."

Ma come accennato in precedenza, è stato a lungo considerato non sicuro farlo.

Nella stragrande maggioranza dei casi puoi evitare problemi semplicemente chiamando i tuoi script Ruby con un "." Anteposto ad es. / script / server.


3

Come sottolineato da Jörg W Mittag, penso che ciò che si desidera utilizzare sia require_relativequindi il file richiesto è relativo al file di origine della requiredichiarazione e non alla directory di lavoro corrente.

Le dipendenze dovrebbero essere relative al file di build del rake.

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.