Ruby on Rails uygulamaları arasında load
ve require
içinde büyük bir fark var mı ? Yoksa ikisi de aynı işlevselliğe mi sahip?
Ruby on Rails uygulamaları arasında load
ve require
içinde büyük bir fark var mı ? Yoksa ikisi de aynı işlevselliğe mi sahip?
Yanıtlar:
require
tüm tanımlı arama yollarında kitaplığı arar ve ayrıca girdiğiniz dosya adına .rb veya .so ekler. Ayrıca, bir kitaplığın yalnızca bir kez dahil edilmesini sağlar. Dolayısıyla, uygulamanız kitaplık A ve B'yi gerektiriyorsa ve kitaplık B kitaplığı A'yı da gerektiriyorsa, yalnızca bir kez yüklenir.
İle load
kütüphanenin tam adını eklemeniz gerekir ve her aradığınızda load
, zaten bellekte olsa bile yüklenir .
require
görmezden gelen $LOADED_FEATURES
( $"
) global dizisi aracılığıyla önceden yüklenmiş olanı izler load
.
Arasındaki bir diğer fark Kernel#require
ve Kernel#load
olmasıdır Kernel#load
anonim boş modüle yüklenen kod kaydırmak olanak tanıyan isteğe bağlı ikinci bir argüman alır.
Maalesef pek kullanışlı değil. Birincisi, load
ed kodunun modülden çıkması, sadece küresel isim alanına erişerek kolaydır , yani hala benzer bir şey ekleyebilirler class ::String; def foo; end end
. İkincisi, load
kodu içine sardığı modülü geri döndürmez, bu yüzden basitçe onu ObjectSpace::each_object(Module)
el ile bulmanız gerekir .
Kernel#load
Başka bir tartışma hakkında hiçbir fikrim yoktu
load
ed kodunun modülden çıkması kolaydır , sadece global isim alanına erişerek, yani hala benzer bir şey ekleyebilirler class ::String; def foo; end end
. İkincisi, load
kodu içine sardığı modülü geri döndürmez, bu yüzden basitçe onu ObjectSpace::each_object(Module)
el ile bulmanız gerekir .
Bir Rails uygulaması çalıştırıyordum ve Gemfile'da "required: false" seçeneğiyle oluşturduğum özel bir cevherim vardı. Şimdi, raylar sunucusunu veya ray konsolunu yüklediğimde, başlatıcıda mücevher gerektirebildim ve mücevher yüklendi. Ancak, rspec ve capybara ile bir özellik testi çalıştırdığımda bir yük hatası aldım. Ve bir testi çalıştırırken Gem'in $ LOAD_PATH'de bulunmamasının nedeni tamamen şaşkına dönmüştüm.
Bu yüzden, rubygemlerin ve paketleyicinin birbirini yükleyen, gerektiren, etkileşim kuran tüm farklı yolları inceledim. Ve bunlar, özel sorunumun çözümünü keşfetmeme yardımcı olan bulgularımın bir özeti:
yük
1) Bir Ruby dosyasına mutlak bir yol iletebilirsiniz ve o dosyadaki kodu çalıştıracaktır.
load('/Users/myuser/foo.rb')
2) Yüklemek için göreceli bir yol geçebilirsiniz. File ile aynı dizindeyseniz, onu bulacaktır:
> load('./foo.rb')
foo.rb loaded!
=> true
Ancak load () ile farklı dizinden bir dosya yüklemeye çalışırsanız, mevcut çalışma dizinine (örneğin ./) dayalı göreceli bir yolla bulamayacaktır:
> load('./foo.rb')
LoadError: cannot load such file -- foo.rb
3) Yukarıda gösterildiği gibi, yükleme her zaman doğru değerini döndürür (dosya yüklenemezse, a'yı yükseltir LoadError
).
4) Global değişkenler, sınıflar, sabitler ve yöntemlerin tümü içe aktarılır, ancak yerel değişkenler değil.
5) Aynı dosyada iki kez yükleme çağırmak, o dosyadaki kodu iki kez çalıştıracaktır. Belirtilen dosya bir sabit tanımlıyorsa, bu sabiti iki kez tanımlayarak bir uyarı oluşturur.
6) $ LOAD_PATH, mutlak yollar dizisidir. Yüklemeyi sadece bir dosya adı geçirirseniz, $ LOAD_PATH üzerinden döngü yapar ve her dizinde dosyayı arar.
> $LOAD_PATH.push("/Users/myuser")
> load('foo.rb')
foo.rb loaded!
=> true
gerek
1) Aynı dosyanın iki kez çağrılması, yalnızca bir kez çalıştırılır. Aynı dosyaya bir kez göreceli yolla ve bir kez de mutlak yolla başvurursanız, aynı dosyayı iki kez yüklemeyecek kadar akıllıca olur.
2) Required, dosya çalıştırıldıysa true, değilse false döndürür.
3) required, $ LOADED_FEATURES global değişkeninde hangi dosyaların önceden yüklenmiş olduğunu takip eder.
4) Dosya uzantısını eklemenize gerek yoktur:
require 'foo'
5) require, foo.rb'yi, aynı zamanda foo.so, foo.o veya foo.dll gibi dinamik kitaplık dosyalarını arayacaktır. Ruby'den C kodunu bu şekilde çağırabilirsiniz.
6), geçerli dizin varsayılan olarak $ LOAD_PATH içinde olmadığından, gerekli geçerli dizini kontrol etmez.
7) require_relative, sürecin çalışma dizinine değil, geçerli dosyaya göre bir yol alır.
Rubygems
1) Rubygems, mücevher adı verilen Ruby kitaplıklarının kurulumunu kolayca yönetmek için tasarlanmış bir paket yöneticisidir.
2) İçeriğini, bazı meta verilerle birlikte kodunuz tarafından içe aktarılabilen bir grup ruby dosyası ve / veya dinamik kitaplık dosyası içeren bir zip dosyası olarak paketler.
3) Rubygems, varsayılan gereksinim yöntemini kendi sürümüyle değiştirir. Bu sürüm, $ LOAD_PATH içindeki dizinlere ek olarak, kurulu gemlerinize de bakacaktır. Rubygems dosyayı mücevherlerinizde bulursa, o mücevheri $ LOAD_PATH'nize ekler.
4) gem install komutu, bir gem'in tüm bağımlılıklarını çözer ve bunları kurar. Aslında, bir mücevherin kendisini kurmadan önce tüm bağımlılıklarını kurar.
Bundler
1) Bundler, projenizin ihtiyaç duyduğu tüm mücevherleri ve isteğe bağlı olarak bu mücevherlerin hangi sürümlerini belirlemenizi sağlar. Ardından, paket komutu tüm bu mücevherleri ve bağımlılıklarını yükler.
2) Gemfile adlı bir dosyada hangi mücevherlere ihtiyacınız olduğunu belirtirsiniz.
3) bundle komutu ayrıca Gemfile.lock'ta listelenen tüm mücevherleri listelenen belirli sürümlerde yükler.
4) bundle exec'yi bir komutun önüne koymak, örneğin bundle exec rspec, gereksiniminizin Gemfile.lock'unuzda belirtilen bir gem sürümünü yüklemesini sağlar.
Raylar ve Bundler
1) config / boot.rb'de, 'bundler / setup'ın çalıştırılmasını gerektirir. Bundler, Ruby'nin Gemfile'daki tüm mücevherleri (ve tüm bağımlılıklarını) bulabilmesini sağlar. 'paketleyici / kurulum' gerektirmesi, Gemfile'ınızı otomatik olarak keşfedecek ve Gemfile'ınızdaki tüm mücevherleri Ruby'nin kullanımına sunacaktır (teknik terimlerle, mücevherleri "yükleme yoluna" koyar). Bunu 'rubygems' gerektirecek bazı ekstra güçler eklemek olarak düşünebilirsiniz.
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
2) Artık kodunuz Ruby tarafından kullanılabilir olduğuna göre, ihtiyacınız olan mücevherleri isteyebilirsiniz. Örneğin, 'sinatra' isteyebilirsiniz. Çok fazla bağımlılığınız varsa, "Gemfile'imdeki tüm değerli taşları gerektir" demek isteyebilirsiniz. Bunu yapmak için, 'paketleyici / kurulum' gerektirmenin hemen arkasına aşağıdaki kodu koyun:
Bundler.require(:default)
3) Varsayılan olarak, Bundler.require'ı çağırmak, Gemfile'ınızdaki her bir mücevher gerektirir. Gemfile'daki satırda gem 'foo',: required => false diyorsa, foo'nun kurulu olduğundan emin olur, ancak gerekli değildir. Cevheri kullanmak istiyorsanız, require ('foo') 'u çağırmanız gerekir.
Böylece, bu bilgi genişliğini göz önünde bulundurarak, testimin konusuna geri döndüm ve Bundler.setup $ LOAD_PATH'a eklediğinden, ancak şunu gerektirdiğinden, rails_helper.rb dosyasındaki cevheri açıkça talep etmem gerektiğini fark ettim, ancak şunu gerektiriyor: false engellendi Bundler.require açıkça gerektirmesini istiyor . Ve sonra sorun çözüldü.
require
,load
ya daautoload
Ruby?