ENV["BUNDLE_GEMFILE"] = File.expand_path("../../Gemfile", __FILE__)
J'essaie juste d'accéder à un fichier .rb à partir du répertoire some et un tutoriel me dit d'utiliser ce code mais je ne vois pas comment il trouve le fichier gem.
ENV["BUNDLE_GEMFILE"] = File.expand_path("../../Gemfile", __FILE__)
J'essaie juste d'accéder à un fichier .rb à partir du répertoire some et un tutoriel me dit d'utiliser ce code mais je ne vois pas comment il trouve le fichier gem.
Réponses:
File.expand_path('../../Gemfile', __FILE__)
est un idiome Ruby quelque peu laid pour obtenir le chemin absolu d'un fichier lorsque vous connaissez le chemin relatif au fichier actuel. Une autre façon de l'écrire est la suivante:
File.expand_path('../Gemfile', File.dirname(__FILE__))
les deux sont laids, mais la première variante est plus courte. La première variante est, cependant, également très peu intuitive jusqu'à ce que vous compreniez bien. Pourquoi le supplément ..
? (mais la deuxième variante peut donner une idée de la raison pour laquelle elle est nécessaire).
Voici comment cela fonctionne: File.expand_path
renvoie le chemin absolu du premier argument, par rapport au deuxième argument (qui par défaut est le répertoire de travail courant). __FILE__
est le chemin vers le fichier dans lequel se trouve le code. Puisque le deuxième argument dans ce cas est un chemin vers un fichier, et File.expand_path
suppose un répertoire, nous devons coller un supplément ..
dans le chemin pour obtenir le chemin correct. Voilà comment cela fonctionne:
File.expand_path
est fondamentalement implémenté comme ceci (dans le code suivant path
aura la valeur ../../Gemfile
et relative_to
aura la valeur 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
(il y a un peu plus à cela, il s'étend ~
au répertoire personnel et ainsi de suite - il y a probablement aussi d'autres problèmes avec le code ci-dessus)
Passer en revue un appel au code ci absolute_path
- dessus obtiendra d'abord la valeur /path/to/file.rb/../../Gemfile
, puis pour chaque tour de la boucle, le premier ..
sera supprimé, avec le composant de chemin avant lui. Le premier /file.rb/..
est supprimé, puis le tour suivant /to/..
est supprimé, et nous obtenons /path/Gemfile
.
Pour faire une histoire courte, File.expand_path('../../Gemfile', __FILE__)
c'est une astuce pour obtenir le chemin absolu d'un fichier lorsque vous connaissez le chemin relatif au fichier courant. Le plus ..
dans le chemin relatif est d'éliminer le nom du fichier dans __FILE__
.
Dans Ruby 2.0, il existe une Kernel
fonction appelée __dir__
qui est implémentée en tant que File.dirname(File.realpath(__FILE__))
.
File.expand_path('../Gemfile',__dir__)
File.expand_path assumes a directory
, même si ce __FILE__
n'est pas un répertoire. Pour que les choses aient un sens, utilisez __dir__
qui est en fait un répertoire.
Deux références:
Je suis tombé sur ceci aujourd'hui:
boot.rb commit dans Rails Github
Si vous remontez de deux répertoires depuis boot.rb dans l'arborescence de répertoires:
/ railties / lib / rails / générateurs / rails / app / templates
vous voyez Gemfile, ce qui me porte à croire que les File.expand_path("../../Gemfile", __FILE__)
références au fichier suivant:/path/to/this/file/../../Gemfile