Ruby 1.9.2 neden "." LOAD_PATH ve alternatifi nedir?


154

Ruby 1.9.2'deki en son değişiklikler artık geçerli dizini .sizin parçanız haline getirmez LOAD_PATH. Ben bir .parçası olduğunu varsayalım Rakefiles önemsiz sayıda var LOAD_PATH, bu yüzden bu onları kırdı (onlar proje yüklemek için tüm gerekli ifadeler için "yüklenecek böyle bir dosya" bildirdi). Bunu yapmak için özel bir gerekçe var mıydı?

Bir düzeltmeye gelince, $: << "."her yere eklemek işe yarıyor, ama inanılmaz derecede kaba görünüyor ve bunu yapmak istemiyorum. Rakefiles 1.9.2+ sürümümü uyumlu hale getirmenin tercih edilen yolu nedir?

Yanıtlar:


141

Bu bir "güvenlik" riski olarak kabul edildi.

Mutlak yolları kullanarak etrafta gezinebilirsiniz

File.expand_path(__FILE__) et al

veya yapıyor

require './filename' (ironically).

veya kullanarak

require_relative 'filename'

veya "içerme" dizini ekleme

ruby -I . ...

veya aynı, irb kullanılarak;

$irb -I .

27
Kullanarak yaralandım require_relative. Teşekkürler.
John Feminella

11
Yürütülebilir dosyaları çalıştırma yolundaki geçerli dizini içermeyen çoğu unix'e benzer mi?
Andrew Grimm

5
require './filename'yalnızca komut dosyanız çalışma dizini, komut dosyasının bulunduğu dizine ayarlanmış olarak yürütüldüğünde çalışır. Çok dizinli projelerde bu genellikle geçerli değildir.
mxcl

34

Bunun iki nedeni var:

  • sağlamlık ve
  • güvenlik

Her ikisi de aynı temel prensibe dayanmaktadır: genel olarak, kodunuz çalıştırıldığında geçerli dizinin ne olduğunu bilemezsiniz. Bu, bir dosyaya ihtiyaç duyduğunuzda ve o dosyanın geçerli dizinde olmasına bağlı olduğunda, o dosyanın orada olup olmayacağını veya orada olmasını beklediğiniz dosya olup olmadığını kontrol etmenin hiçbir yolu olmadığı anlamına gelir.


5
İki dosyanın birbirine göre aynı konumda olmasının zorunlu olarak kötü bir gereklilik olduğunu düşünmüyorum. Eğer bu doğru olsaydı, dizinler için hiçbir işe yaramazdık.
John Feminella

4
@John Feminella: Bunun, dosyaları birbirine göre yollara koymakla ne ilgisi var? Soru, onları .geçerli çalışma dizinine göreceli olarak koymakla ilgilidir . Kullanıcı cdfarklı bir dizine girerse, geçerli çalışma dizini değişir ve artık komut dosyanızı çağırdığında kullanıcının bulunduğu dizine bağlı olarak require tamamen farklı dosyalar elde edersiniz. Bunun iyi bir fikir olduğunu sanmıyorum.
Jörg W Mittag

Peki iyi bir arayüz korumak için, bunu yapmak gerekir? $: << File.dirname(__FILE__)
Joshua Cheek

4
@Joshua Cheek: Şahsen ben bundan hoşlanmıyorum. (Ama lütfen eski koduma bakma çünkü bu tür şeylerle doludur :-)). Ben sadece taklit olduğunu libdizin üzerinde $LOAD_PATHve daha sonra requiregöreli tüm dosyaları lib. Başka bir deyişle: $LOAD_PATHDoğru şekilde nasıl ayarlanacağını bulmak için yöneticiye bırakıyorum . RubyGems kullanıyorsanız, bu çok önemlidir, çünkü RubyGems bunu sizin için otomatik olarak yapar ve Debian paketleri kullanıyorsanız, paket bakımcının işi budur. Sonuçta, oldukça güzel çalışıyor gibi görünüyor.
Jörg W Mittag

8
@Joshua Yanak: Ayrıca, bir denge unsuru çeşit-itibarıyla çıkarmadan .gelen $LOAD_PATHYakut 1.9.2 sunmakta, require_relativehangi ... Sürpriz ... requireşu anda yürütülen dosyanın konumuna sa dosya göreli (yani göreceli File.dirname(__FILE__)).
Jörg W Mittag

16

Diğer yanıtların da belirttiği gibi, bu bir güvenlik riskidir çünkü .yükleme yolunuzda Dir.pwd, şu andaki dosyanın dizinini değil, mevcut çalışma dizinini belirtir . Yani betiğinizi kim çalıştırıyorsa cdbunu başka bir dizine girerek değiştirebilirsiniz . İyi değil!

__FILE__Alternatif olarak inşa edilmiş tam yolları kullanıyorum .

require File.expand_path(File.join(File.dirname(__FILE__), 'filename'))

Bunun aksine require_relative, Ruby 1.8.7 ile geriye doğru uyumludur.


4
Bu varyasyon da var (ki ben şahsen daha okunabilir buluyorum): require Pathname.new(__FILE__).dirname + 'filename'
Tyler Rick

8

kullanım require_relative 'file_to_require'

1.8.7'de Require_Reative çalışması yapmak için bunu kodunuza atın:

unless Kernel.respond_to?(:require_relative)
  module Kernel
    def require_relative(path)
      require File.join(File.dirname(caller.first), path.to_str)
    end
  end
end


3

Birkaç şey fark edene kadar bunu kafa karıştırıcı bir değişiklik olarak buldum.

RUBYLIB dosyasını .profile (Unix) olarak ayarlayabilir ve daha önce yaptığınız gibi hayata devam edebilirsiniz:

export RUBYLIB="."

Ancak yukarıda belirtildiği gibi, uzun zamandır bunu yapmak güvensiz kabul ediliyor.

Vakaların büyük çoğunluğu için Ruby komut dosyalarınızı önceden eklenmiş bir '.' İle çağırarak sorunlardan kaçınabilirsiniz. örneğin ./scripts/server.


3

Jörg W Mittag'in işaret ettiği gibi, kullanmak istediğiniz şeyin , geçerli require_relativedosya requiredirektifinin değil, bildirimin kaynak dosyasına göreceli olması gerektiğini düşünüyorum .

Bağımlılıklarınız komisyon oluşturma dosyanıza göreli olmalıdır.

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.