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.
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:
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_pathrenvoie 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_pathsuppose un répertoire, nous devons coller un supplément ..dans le chemin pour obtenir le chemin correct. Voilà comment cela fonctionne:
File.expand_pathest fondamentalement implémenté comme ceci (dans le code suivant pathaura la valeur ../../Gemfileet relative_toaura la valeur 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
(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 Kernelfonction appelée __dir__qui est implémentée en tant que File.dirname(File.realpath(__FILE__)).
Y a-t-il une raison pour laquelle vous ne devriez pas simplement utiliser 'require_relative' autre que l'incompatibilité avec la version antérieure à Ruby 1.9.2?
Danny Andrews
9
À partir de Ruby 2.0, vous pouvez utiliserFile.expand_path('../Gemfile',__dir__)
Phrogz
Cette ligne de Theo m'a finalement permis de cliquer pour moi 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.
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
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, etFile.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 suivantpath
aura la valeur../../Gemfile
etrelative_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 queFile.dirname(File.realpath(__FILE__))
.la source
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:
__FILE__
marche dans RubyJe 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
la source