File.expand_path('../../Gemfile', __FILE__)
ist eine etwas hässliche Ruby-Redewendung, um den absoluten Pfad zu einer Datei zu erhalten, wenn Sie den Pfad relativ zur aktuellen Datei kennen. Eine andere Art zu schreiben ist folgende:
File.expand_path('../Gemfile', File.dirname(__FILE__))
beide sind hässlich, aber die erste Variante ist kürzer. Die erste Variante ist jedoch auch sehr unintuitiv, bis Sie den Dreh raus haben. Warum das Extra ..
? (aber die zweite Variante kann einen Hinweis darauf geben, warum es benötigt wird).
So funktioniert es: File.expand_path
Gibt den absoluten Pfad des ersten Arguments relativ zum zweiten Argument zurück (standardmäßig das aktuelle Arbeitsverzeichnis). __FILE__
ist der Pfad zu der Datei, in der sich der Code befindet. Da das zweite Argument in diesem Fall ein Pfad zu einer Datei ist und File.expand_path
ein Verzeichnis annimmt, müssen wir ein zusätzliches ..
in den Pfad einfügen, um den Pfad richtig zu machen. So funktioniert es:
File.expand_path
wird im Grunde so implementiert (im folgenden Code path
wird der Wert von ../../Gemfile
und relative_to
wird den Wert von haben /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
(Es steckt ein bisschen mehr dahinter, es wird ~
in das Home-Verzeichnis erweitert und so weiter - es gibt wahrscheinlich auch einige andere Probleme mit dem obigen Code)
Wenn Sie einen Aufruf des obigen Codes durchlaufen, absolute_path
wird zuerst der Wert abgerufen /path/to/file.rb/../../Gemfile
, und für jede Runde in der Schleife wird die erste ..
zusammen mit der Pfadkomponente davor entfernt. Zuerst /file.rb/..
wird entfernt, dann wird in der nächsten Runde /to/..
entfernt, und wir bekommen /path/Gemfile
.
Um es kurz zu machen, es File.expand_path('../../Gemfile', __FILE__)
ist ein Trick, den absoluten Pfad einer Datei zu ermitteln, wenn Sie den Pfad relativ zur aktuellen Datei kennen. Das Extra ..
im relativen Pfad besteht darin, den Namen der Datei in zu entfernen __FILE__
.
In Ruby 2.0 gibt es eine Kernel
Funktion namens __dir__
, die als implementiert ist File.dirname(File.realpath(__FILE__))
.