Pertanyaan File.expand_path (“../../ Gemfile”, __FILE__) Bagaimana cara kerjanya? Di mana file itu?


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

Saya hanya mencoba mengakses file .rb dari beberapa direktori dan tutorial memberitahu saya untuk menggunakan kode ini tetapi saya tidak melihat bagaimana ia menemukan file gem.


75
2017-12-17 21:31


asal


Jawaban:


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

adalah idiom Ruby yang agak jelek untuk mendapatkan path absolut ke file ketika Anda mengetahui path relatif ke file saat ini. Cara lain untuk menulisnya adalah ini:

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

keduanya jelek, tetapi varian pertama lebih pendek. Varian pertama, bagaimanapun, juga sangat tidak intuitif sampai Anda menguasainya. Kenapa ekstra ..? (tetapi varian kedua dapat memberi petunjuk mengapa diperlukan).

Begini Cara kerjanya: File.expand_path mengembalikan jalur absolut dari argumen pertama, relatif terhadap argumen kedua (yang default ke direktori kerja saat ini). __FILE__ adalah path ke file yang di kode. Karena argumen kedua dalam hal ini adalah path ke file, dan File.expand_path mengasumsikan direktori, kita harus tetap ekstra .. di jalur untuk mendapatkan jalan yang benar. Begini Cara kerjanya:

File.expand_path pada dasarnya diimplementasikan seperti ini (dalam kode berikut path akan memiliki nilai ../../Gemfile dan relative_to akan memiliki nilai /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

(ada sedikit lebih dari itu, itu mengembang ~ ke direktori home dan sebagainya - mungkin ada juga beberapa masalah lain dengan kode di atas)

Melangkah melalui panggilan ke kode di atas absolute_path pertama akan mendapatkan nilainya /path/to/file.rb/../../Gemfile, lalu untuk setiap putaran di loop yang pertama .. akan dihapus, bersama dengan komponen jalur sebelumnya. Pertama /file.rb/.. dihapus, lalu pada ronde selanjutnya /to/.. dihapus, dan kita dapatkan /path/Gemfile.

Singkat cerita, File.expand_path('../../Gemfile', __FILE__) adalah trik untuk mendapatkan path absolut dari file ketika Anda mengetahui path relatif ke file saat ini. Ekstra .. di jalur relatif adalah menghilangkan nama file di __FILE__.

Di Ruby 2.0 ada a Kernel fungsi yang disebut __dir__ yang diimplementasikan sebagai File.dirname(File.realpath(__FILE__)).


173
2017-12-18 20:11



Dua referensi:

  1. Dokumentasi file File :: expand_path
  2. Bagaimana __FILE__ bekerja di Ruby

Saya menemukan ini hari ini:

boot.rb melakukan commit di Rails Github

Jika Anda membuka dua direktori dari boot.rb di pohon direktori:

/ railties / lib / rails / generator / rel / aplikasi / template

Anda melihat Gemfile, yang membuat saya percaya itu File.expand_path("../../Gemfile", __FILE__) referensi file berikut: /path/to/this/file/../../Gemfile


9
2017-12-17 21:57