ENV["BUNDLE_GEMFILE"] = File.expand_path("../../Gemfile", __FILE__)
Sto solo cercando di accedere a un file .rb dalla directory some e un tutorial mi dice di usare questo codice ma non vedo come sta trovando il file gem.
ENV["BUNDLE_GEMFILE"] = File.expand_path("../../Gemfile", __FILE__)
Sto solo cercando di accedere a un file .rb dalla directory some e un tutorial mi dice di usare questo codice ma non vedo come sta trovando il file gem.
Risposte:
File.expand_path('../../Gemfile', __FILE__)
è un idioma Ruby un po 'brutto per ottenere il percorso assoluto di un file quando si conosce il percorso relativo al file corrente. Un altro modo per scriverlo è questo:
File.expand_path('../Gemfile', File.dirname(__FILE__))
entrambi sono brutti, ma la prima variante è più corta. La prima variante è, tuttavia, anche molto non intuitiva finché non ci si prende la mano. Perché l'extra ..
? (ma la seconda variante può dare un indizio sul motivo per cui è necessaria).
Funziona così: File.expand_path
restituisce il percorso assoluto del primo argomento, relativo al secondo argomento (che per impostazione predefinita è la directory di lavoro corrente). __FILE__
è il percorso del file in cui si trova il codice. Poiché il secondo argomento in questo caso è un percorso di un file e File.expand_path
presuppone una directory, dobbiamo inserire un extra ..
nel percorso per ottenere il percorso corretto. È così che funziona:
File.expand_path
è fondamentalmente implementato in questo modo (nel codice seguente path
avrà il valore di ../../Gemfile
e relative_to
avrà il valore di /path/to/file.rb
):
def File.expand_path(path, relative_to=Dir.getwd)
# first the two arguments are concatenated, with the second argument first
absolute_path = File.join(relative_to, path)
while absolute_path.include?('..')
# remove the first occurrence of /<something>/..
absolute_path = absolute_path.sub(%r{/[^/]+/\.\.}, '')
end
absolute_path
end
(c'è qualcosa in più, si espande ~
nella directory home e così via - probabilmente ci sono anche altri problemi con il codice sopra)
Passando attraverso una chiamata al codice sopra absolute_path
si otterrà prima il valore /path/to/file.rb/../../Gemfile
, quindi per ogni round nel ciclo il primo ..
verrà rimosso, insieme al componente percorso prima di esso. Il primo /file.rb/..
viene rimosso, quindi il round successivo /to/..
viene rimosso e otteniamo /path/Gemfile
.
Per farla breve, File.expand_path('../../Gemfile', __FILE__)
è un trucco per ottenere il percorso assoluto di un file quando si conosce il percorso relativo al file corrente. L'extra ..
nel percorso relativo è eliminare il nome del file in __FILE__
.
In Ruby 2.0 c'è una Kernel
funzione chiamata __dir__
che è implementata come File.dirname(File.realpath(__FILE__))
.
File.expand_path('../Gemfile',__dir__)
File.expand_path assumes a directory
, anche se __FILE__
non è una directory. Affinché le cose abbiano un senso usa __dir__
che in realtà è una directory.
Due riferimenti:
Mi sono imbattuto in questo oggi:
boot.rb commit in Rails Github
Se salite due directory da boot.rb nell'albero delle directory:
/ railties / lib / rails / generators / rails / app / templates
vedi Gemfile, il che mi porta a crederci File.expand_path("../../Gemfile", __FILE__)
riferimento al seguente file:/path/to/this/file/../../Gemfile