Frage File.expand_path ("../../ Gemfile", __FILE__) Wie funktioniert das? Wo ist die Datei?


ENV["BUNDLE_GEMFILE"] = File.expand_path("../../Gemfile", __FILE__)

Ich versuche nur, auf eine .rb-Datei aus dem Verzeichnis zuzugreifen, und ein Tutorial sagt mir, dass ich diesen Code verwenden soll, aber ich sehe nicht, wie es die Edelsteindatei findet.


75
2017-12-17 21:31


Ursprung


Antworten:


File.expand_path('../../Gemfile', __FILE__)

ist ein etwas hässliches Ruby-Idiom, um den absoluten Pfad zu einer Datei zu erhalten, wenn Sie den relativen Pfad zur aktuellen Datei kennen. Eine andere Art, es zu schreiben, ist dies:

File.expand_path('../Gemfile', File.dirname(__FILE__))

beide sind hässlich, aber die erste Variante ist kürzer. Die erste Variante ist aber auch sehr intuitiv, bis man den Dreh raus hat. Warum das Extra ..? (aber die zweite Variante kann einen Hinweis 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 nimmt ein Verzeichnis an, wir müssen extra einkleben .. auf dem Weg, um den richtigen Weg zu finden. So funktioniert es:

File.expand_path ist grundsätzlich so implementiert (im folgenden Code) path wird den Wert von haben ../../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 gibt ein bisschen mehr, es dehnt sich aus ~ zum Home-Verzeichnis und so weiter - es gibt wahrscheinlich auch einige andere Probleme mit dem obigen Code)

Einen Anruf zum obigen Code durchgehen absolute_path erhält zuerst den Wert /path/to/file.rb/../../Gemfile, dann für jede Runde in der Schleife die erste .. wird zusammen mit der Pfadkomponente davor entfernt. Zuerst /file.rb/.. wird entfernt, dann in der nächsten Runde /to/.. ist entfernt, und wir bekommen /path/Gemfile.

Um es kurz zu machen, File.expand_path('../../Gemfile', __FILE__) ist ein Trick, um den absoluten Pfad einer Datei zu erhalten, wenn Sie den Pfad relativ zur aktuellen Datei kennen. Das Extra .. im relativen Pfad ist es, den Namen der Datei in zu löschen __FILE__.

In Ruby 2.0 gibt es ein Kernel Funktion aufgerufen __dir__ das ist implementiert als File.dirname(File.realpath(__FILE__)).


173
2017-12-18 20:11



Zwei Referenzen:

  1. Dokumentation der Datei :: expand_path-Methode
  2. Wie geht es? __FILE__ arbeite in Ruby

Ich bin heute darüber gestolpert:

boot.rb commit im Rails Github

Wenn Sie zwei Verzeichnisse von boot.rb in der Verzeichnisstruktur nach oben gehen:

/ railties / lib / schienen / generatoren / schienen / app / templates

Du siehst Gemfile, was mich dazu bringt, das zu glauben File.expand_path("../../Gemfile", __FILE__) Referenzen folgende Datei: /path/to/this/file/../../Gemfile


9
2017-12-17 21:57