Solo estoy tratando de acceder a un archivo .rb desde el directorio some y un tutorial me dice que use este código, pero no veo cómo está encontrando el archivo gem.
es un modismo de Ruby algo feo para obtener la ruta absoluta a un archivo cuando conoce la ruta relativa al archivo actual. Otra forma de escribirlo es esta:
ambos son feos, pero la primera variante es más corta. Sin embargo, la primera variante tampoco es muy intuitiva hasta que la domines. ¿Por qué el extra ..? (pero la segunda variante puede dar una pista de por qué se necesita).
Así es como funciona: File.expand_pathdevuelve la ruta absoluta del primer argumento, en relación con el segundo argumento (que por defecto es el directorio de trabajo actual). __FILE__es la ruta al archivo en el que se encuentra el código. Dado que el segundo argumento en este caso es una ruta a un archivo, y File.expand_pathasume un directorio, tenemos que colocar un extra ..en la ruta para obtener la ruta correcta. Así es como funciona:
File.expand_pathse implementa básicamente así (en el siguiente código pathtendrá el valor de ../../Gemfiley relative_totendrá el valor de /path/to/file.rb):
defFile.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
(hay un poco más, se expande ~al directorio de inicio y así sucesivamente; probablemente también haya otros problemas con el código anterior)
Al realizar una llamada al código anterior absolute_path, primero obtendrá el valor /path/to/file.rb/../../Gemfile, luego, para cada ronda del ciclo .., se eliminará la primera , junto con el componente de ruta anterior. Primero /file.rb/..se elimina, luego en la siguiente ronda /to/..se elimina y obtenemos /path/Gemfile.
En resumidas cuentas, File.expand_path('../../Gemfile', __FILE__)es un truco obtener la ruta absoluta de un archivo cuando se conoce la ruta relativa al archivo actual. El extra ..en la ruta relativa es eliminar el nombre del archivo en formato __FILE__.
En Ruby 2.0 hay una Kernelfunción llamada __dir__que se implementa como File.dirname(File.realpath(__FILE__)).
¿Hay alguna razón por la que no debería usar 'require_relative' que no sea la incompatibilidad con Ruby 1.9.2 anterior?
Danny Andrews
9
A partir de Ruby 2.0 puede usarFile.expand_path('../Gemfile',__dir__)
Phrogz
Esta línea de Theo finalmente consiguió hacer clic para mí File.expand_path assumes a directory, aunque __FILE__no es un directorio. Para que las cosas tengan sentido, use __dir__que en realidad es un directorio.
ves Gemfile, lo que me lleva a creer que hace File.expand_path("../../Gemfile", __FILE__)referencia al siguiente archivo:/path/to/this/file/../../Gemfile
Respuestas:
File.expand_path('../../Gemfile', __FILE__)
es un modismo de Ruby algo feo para obtener la ruta absoluta a un archivo cuando conoce la ruta relativa al archivo actual. Otra forma de escribirlo es esta:
File.expand_path('../Gemfile', File.dirname(__FILE__))
ambos son feos, pero la primera variante es más corta. Sin embargo, la primera variante tampoco es muy intuitiva hasta que la domines. ¿Por qué el extra
..
? (pero la segunda variante puede dar una pista de por qué se necesita).Así es como funciona:
File.expand_path
devuelve la ruta absoluta del primer argumento, en relación con el segundo argumento (que por defecto es el directorio de trabajo actual).__FILE__
es la ruta al archivo en el que se encuentra el código. Dado que el segundo argumento en este caso es una ruta a un archivo, yFile.expand_path
asume un directorio, tenemos que colocar un extra..
en la ruta para obtener la ruta correcta. Así es como funciona:File.expand_path
se implementa básicamente así (en el siguiente códigopath
tendrá el valor de../../Gemfile
yrelative_to
tendrá el valor de/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
(hay un poco más, se expande
~
al directorio de inicio y así sucesivamente; probablemente también haya otros problemas con el código anterior)Al realizar una llamada al código anterior
absolute_path
, primero obtendrá el valor/path/to/file.rb/../../Gemfile
, luego, para cada ronda del ciclo..
, se eliminará la primera , junto con el componente de ruta anterior. Primero/file.rb/..
se elimina, luego en la siguiente ronda/to/..
se elimina y obtenemos/path/Gemfile
.En resumidas cuentas,
File.expand_path('../../Gemfile', __FILE__)
es un truco obtener la ruta absoluta de un archivo cuando se conoce la ruta relativa al archivo actual. El extra..
en la ruta relativa es eliminar el nombre del archivo en formato__FILE__
.En Ruby 2.0 hay una
Kernel
función llamada__dir__
que se implementa comoFile.dirname(File.realpath(__FILE__))
.fuente
File.expand_path('../Gemfile',__dir__)
File.expand_path assumes a directory
, aunque__FILE__
no es un directorio. Para que las cosas tengan sentido, use__dir__
que en realidad es un directorio.Dos referencias:
__FILE__
funciona en Ruby?Me encontré con esto hoy:
boot.rb confirmado en Rails Github
Si sube dos directorios desde boot.rb en el árbol de directorios:
/ railties / lib / rails / generators / rails / app / templates
ves Gemfile, lo que me lleva a creer que hace
File.expand_path("../../Gemfile", __FILE__)
referencia al siguiente archivo:/path/to/this/file/../../Gemfile
fuente