File.expand_path (“../../ Gemfile”, __FILE__) Bu nasıl çalışır? Dosya nerede?


84

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

Sadece bir dizinden bir .rb dosyasına erişmeye çalışıyorum ve bir eğitim bana bu kodu kullanmamı söylüyor, ancak gem dosyasını nasıl bulduğunu anlamıyorum.


Yanıtlar:


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

mevcut dosyaya göre yolu bildiğinizde bir dosyanın mutlak yolunu elde etmek için biraz çirkin bir Ruby deyimidir. Bunu yazmanın başka bir yolu da şudur:

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

ikisi de çirkin ama ilk varyant daha kısa. Bununla birlikte, ilk varyant, siz onu asana kadar çok sezgisel değildir. Neden fazlalık ..? (ancak ikinci değişken, neden gerekli olduğuna dair bir ipucu verebilir).

İşleyiş şekli şöyledir: File.expand_pathikinci bağımsız değişkene göre ilk bağımsız değişkenin mutlak yolunu döndürür (varsayılan olarak geçerli çalışma dizinidir). __FILE__kodun bulunduğu dosyanın yoludur. Bu durumda ikinci argüman bir dosyaya giden bir yol olduğundan ve File.expand_pathbir dizin varsaydığından .., yolu doğru almak için yola fazladan bir tane yapıştırmalıyız . Bu nasıl çalışır:

File.expand_pathTemelde (Aşağıdaki kodda böyle uygulanmaktadır pathdeğerini sahip olacak ../../Gemfileve relative_todeğerini sahip olacaktır /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

(biraz daha fazlası var, ~ana dizine genişliyor ve benzeri - muhtemelen yukarıdaki kodla ilgili başka sorunlar da var)

Yukarıdaki koda yapılan bir çağrıda ilerlemek absolute_pathönce değeri alır /path/to/file.rb/../../Gemfile, ardından döngüdeki her tur için ilki .., ondan önceki yol bileşeni ile birlikte kaldırılır. Önce /file.rb/..kaldırılır, sonra bir sonraki turda /to/..kaldırılır ve alırız /path/Gemfile.

Uzun lafın kısası, File.expand_path('../../Gemfile', __FILE__)mevcut dosyaya göre yolu bildiğinizde bir dosyanın mutlak yolunu elde etmek için bir hiledir. ..Göreceli yoldaki fazlalık , içindeki dosyanın adını ortadan kaldırmaktır __FILE__.

Ruby 2.0 bir hayır vardır Kerneldenir fonksiyon __dir__olarak uygulanır File.dirname(File.realpath(__FILE__)).


2
Ruby 1.9.2 öncesi uyumsuzluk dışında sadece 'require_relative' kullanmamanız için herhangi bir sebep var mı?
Danny Andrews

9
Ruby 2.0'dan itibaren kullanabilirsinizFile.expand_path('../Gemfile',__dir__)
Phrogz

Theo'dan gelen bu satır, bir dizin File.expand_path assumes a directoryolmasa __FILE__da nihayet benim için tıkladı. Şeylerin mantıklı olması için, __dir__hangisinin aslında bir dizin olduğunu kullanın.
mbigras

9

İki referans:

  1. Dosya :: expand_path yöntemi belgeleri
  2. __FILE__Ruby'de nasıl çalışır?

Bugün buna rastladım:

Rails Github'da boot.rb commit

Dizin ağacındaki boot.rb'den iki dizin yukarı çıkarsanız:

/ railties / lib / rails / jeneratörler / rails / app / templates

Gemfile'ı görüyorsunuz, bu da beni File.expand_path("../../Gemfile", __FILE__)dosyanın aşağıdaki referanslara inanmasına neden oluyor :/path/to/this/file/../../Gemfile


Gönderi için teşekkürler, ama bu gembundler eğitiminden geldi, bu yüzden tam olarak nasıl sahip olduklarını anlamaya çalışıyordum :)
thenengah
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.