Rails 3'te lib klasöründen modül / sınıf yüklemenin en iyi yolu?


273

En son Rails 3 sürümü, modülleri ve lib sınıflarını otomatik olarak yüklemediğinden, bunları yüklemenin en iyi yolu ne olurdu?

Github'dan:

A few changes were done in this commit:

Do not autoload code in *lib* for applications (now you need to explicitly 
require them). This makes an application behave closer to an engine 
(code in lib is still autoloaded for plugins);

Yanıtlar:


251

Rails 2.3.9 itibariyle,config/application.rb otomatik olarak yüklenmesini istediğiniz dosyaları içeren dizinleri belirtebileceğiniz bir ayar vardır .

Application.rb'den:

# Custom directories with classes and modules you want to be autoloadable.
# config.autoload_paths += %W(#{config.root}/extras)

7
Eğer tüm alt ağacı özdevinimli_yükle isteyen varsa müteşekkir yıllardan @ Not da cevap app/lib.
Tom Harrison

199
# Autoload lib/ folder including all subdirectories
config.autoload_paths += Dir["#{config.root}/lib/**/"]

Kaynak: Rails 3 Quicktip: Tüm alt dizinleri içeren lib dizinini otomatik yükle, tembel yüklemeden kaçının

Lütfen lib klasöründe bulunan dosyaların yalnızca sunucu başlatıldığında yüklendiğini unutmayın. Konforun bu dosyaları otomatik olarak yüklemesini istiyorsanız, şunu okuyun: Rails 3 Quicktip: Geliştirme klasörlerindeki lib klasörlerini otomatik olarak yeniden yükle . Kalıcı yeniden yükleme makineyi yavaşlattığından bunun bir üretim ortamı için olmadığını unutmayın.


Bağlantılar öldü
Besi

84

Otomatik yükleme işlerinin büyüsü

Otomatik yükleme işlerinin yapıldığı klasörleri kontrol etme seçeneğinin diğer yanıtlarda yeterince ele alındığını düşünüyorum. Ancak, başka birinin otomatik yükleme yollarını gerektiği gibi değiştirmiş olsa da yüklenen sorunlara sahip olması durumunda, bu cevap bu otomatik yükleme şeyin arkasındaki sihrin ne olduğunu açıklamaya çalışır.

Yani alt dizinlerden bir şeyler yüklemek söz konusu olduğunda, farkında olmalısınız. Bazen Ruby / Rails büyüsü (bu sefer çoğunlukla Rails) bir şeyin neden olduğunu anlamayı zorlaştırabilir. Otomatik yükleme yollarında bildirilen tüm modüller yalnızca modül adı üst dizin adına karşılık geliyorsa yüklenir. Yani böyle bir lib/my_stuff/bar.rbşeye koymaya çalıştığınızda :

module Foo
  class Bar
  end
end

Otomatik olarak yüklenmez. Sonra tekrar size ebeveyn dir adlandırmak eğer foobu şekilde yoluna adresinden modülü barındıran: lib/foo/bar.rb. Senin için orada olacak. Başka bir seçenek de modül adıyla otomatik olarak yüklenmesini istediğiniz dosyayı adlandırmaktır. Açıkçası bu isimle sadece bir dosya olabilir. Eşyalarınızı birçok dosyaya bölmeniz gerekiyorsa, elbette bir dosyayı diğer dosyaları gerektirecek şekilde kullanabilirsiniz, ancak bunu önermiyorum çünkü geliştirme modundayken ve diğer dosyaları değiştirdiğinizde Rails otomatik olarak yapamıyor onları sizin için yeniden yükleyin. Ancak gerçekten isterseniz, modül adına göre bir dosyaya sahip olabilirsiniz, bu da modülü kullanmak için gereken gerçek dosyaları belirtir. Böylece iki dosyanız olabilir: lib/my_stuff/bar.rbve lib/my_stuff/foo.rbbirincisi yukarıdakiyle aynıdır ve ikincisi tek bir satır içerir:require "bar"ve bu da aynı şekilde işe yarayacaktır.

PS: Bir önemli şey daha eklemek zorunda hissediyorum. Son zamanlarda, lib dizininde otomatik olarak yüklenmesi gereken bir şey olmasını istediğimde, bu proje için özel olarak geliştirdiğim bir şeyse (genellikle, bir gün olabilir) birçok projede kullanılan bir "statik" kod pasajına veya bir git alt modülüne, vb. dönüşür. bu durumda kesinlikle lib klasöründe olmalıdır) o zaman yeri hiç lib klasöründe değildir. Belki de uygulama klasörü altında bir alt klasörde olmalıdır · Ben bu şeyler yapmak için yeni raylar yolu olduğunu hissediyorum. Açıkçası, aynı sihir, eşyalarınızı koyduğunuz yerlerde otomatik yükleme yollarının olduğu her yerde çalışıyor, bu yüzden bu şeylere iyi geliyor. Her neyse, bu konu hakkındaki düşüncelerim. Katılmakta özgürsünüz. :)


GÜNCELLEME: Sihir türü hakkında ..

Severin yorumunda işaret ettiği gibi, çekirdek "bir modül mekanizmasını otomatik yükle" emin Ruby'in bir parçasıdır, ancak otomatik yükleme yolları şeyler değildir. Yapmak için raylara ihtiyacınız yokautoload :Foo, File.join(Rails.root, "lib", "my_stuff", "bar"). Ve Foo modülüne ilk kez başvurmaya çalıştığınızda, o zaman sizin için yüklenir. Bununla birlikte, Rails'in yaptığı şey, bize kayıtlı klasörlerden otomatik olarak bir şeyler yüklemeye ve yüklemeye yönelik bir yol sağlar ve bu, adlandırma kuralları hakkında bir şey varsayması gerektiği şekilde uygulanmıştır. Bu şekilde uygulanmadıysa, şu anda yüklü olmayan bir şeye başvurduğunuzda, tüm otomatik yükleme klasörlerindeki tüm dosyaları gözden geçirmeli ve bunlardan herhangi birinin referans vermeye çalıştığınız içeriği içerip içermediğini kontrol etmelisiniz. Bu da otomatik yükleme ve otomatik yeniden yükleme fikrini yener. Ancak, bu kurallar uygulandığında, tanımlanabileceği yere yüklemeye çalışmanız ve sadece yüklemeniz modül / sınıftan düşebilir.


1
Neden bu Ruby büyüsü? Ruby sadece (tanımsız) bir sabite erişirken yüklenen bir dosyaya komut vermek için kullanabileceğiniz Modül # otomatik yükleme işlevini sağlar (bkz. Ruby-doc.org/core-1.9.3/Module.html#method-i-autoload ). Modül / sınıf adlarının dizinler / dosyalar ile eşleştirilmesi benim görüşüme göre Rails / ActiveSupport'ta yapılmıştır (örneğin: github.com/rails/rails/blob/… ). Yanlış mıyım?
severin

Evet, doğru olduğuna inanıyorum. Zabba "kusurunu" gösterdiğinde orijinal cevabımı "düzeltmek" için çok aceleci davrandım. Bu sorunu açıklığa kavuşturmak için cevabımı biraz daha güncelleyeyim.
Timo

1
Yarım saat kadar zaman geçiriyorum. Sprockets :: JSRender :: İşlemci otomatik yüklemek için gerekli (istedim). Bunun yolu raylar konsoluna girerek ve "Sprockets :: JSRender :: İşlemci" .underscore yaparak ve "sprockets / js_render / işlemci" (.rb eklenmiş) HTH birisi olduğunu söyleyerek bulunabilir.
pedz

Aklımı kurtardın. ~ rahatlama derin iç ~ paylaşım için çok teşekkür ederim :)
Brenden

Bu en yararlı yorum için teşekkür ederim. Yorumunuzu okuyana kadar bazı modüllerin neden olduğu gibi davrandığını anlamadım. Bereket sana!
mjnissim

41

Uyarı: Eğer 'lib' klasörünüzden 'maymun yamasını' ya da 'açık sınıfı' yüklemek istiyorsanız, 'otomatik yükle ' yaklaşımını kullanmayın !!!

  • " config.autoload_paths " yaklaşımı: yalnızca yalnızca BİR yerde tanımlanan bir sınıf yüklüyorsanız çalışır. Bir sınıf zaten başka bir yerde tanımlanmışsa, bu yaklaşımla tekrar yükleyemezsiniz.

  • " config / initializer / load_rb_file.rb " yaklaşımı: her zaman işe yarar ! hedef sınıf ne olursa olsun mevcut sınıf için yeni bir sınıf ya da "açık sınıf" ya da "maymun yaması" olursa, her zaman işe yarar!

Daha fazla ayrıntı için bkz. Https://stackoverflow.com/a/6797707/445908


6
Bu anlaşılması kritik bir ayrım. Bunun için teşekkürler.
Tyler Collier

28

Çok benzer, ama bunun biraz daha zarif olduğunu düşünüyorum:

config.autoload_paths += Dir["#{config.root}/lib", "#{config.root}/lib/**/"]

18

Benim durumumda sadece doğrudan lib dir altında bir dosya yüklemeye çalışıyordum.

Application.rb içinde ...

require '/lib/this_file.rb' 

Konsolda bile çalışmıyordu ve sonra denediğimde

require './lib/this_file.rb' 

ve raylar dosyayı mükemmel bir şekilde yükler.

Hala oldukça çaylakım ve bunun neden işe yaradığından emin değilim ama işe yarıyor. Birisi bana açıklamak isterse çok memnun olurum: DI umarım bu her iki şekilde de yardımcı olur.


2
Çünkü ./lib/this_file.rb geçerli dizine bakar (Rails konsolunda, bu Rails kökünüz olur) ve /lib/this_file.rb bunu mutlak bir yol olarak arar. Örnek: ./lib/this_file.rb = /var/www/myrailsapp/lib/this_file.rb, /lib/this_file.rb = /lib/this_file.rb
Jason

7

Ben de aynı problemi yaşadım. İşte böyle çözdüm. Çözüm, lib dizinini ve tüm alt dizinleri yükler (yalnızca doğrudan değil). Elbette bunu tüm dizinler için kullanabilirsiniz.

# application.rb
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]

5
Bu, tamamen toplayıcı Rails ad alanı kurallarının kötü yan etkisine sahiptir. Eğer auto / bar / foo.rb tanımlayan Bar :: Foo, lib / foo.rb tanımlanmadan önce otomatik yük aramada Foo tanımlanmadan önce görünürse, Expected lib/bar/foo.rb to define constant Foofoo'ya başvurarak lib / foo.rb dosyasını yüklemeye çalışmanız gibi kafa karıştırıcı hatalar alırsınız. sabiti.
Jacob

5

config.autoload_paths benim için çalışmıyor. Başka şekilde çözerim

Ruby on rails 3 kodu / lib klasöründen otomatik olarak yeniden yüklemez (otomatik yükle). İçine koyarak çözerimApplicationController

Dir["lib/**/*.rb"].each do |path|
  require_dependency path
end 

4

Yalnızca belirli dosyaların lib'deki modüllere erişmesi gerekiyorsa, gereken dosyalara bir Require deyimi eklemeniz yeterlidir. Örneğin, bir modelin bir modüle erişmesi gerekiyorsa şunları ekleyin:

require 'mymodule'

model.rb dosyasının en üstüne yerleştirin.


50
requireBir raylar uygulaması içinde kullanmamalısınız , çünkü ActiveSupport::Dependenciesbu kodu düzgün bir şekilde yüklemeyi engeller . Bunun yerine config.autoload_pathsyukarıdaki yanıt gibi kullanmanız ve ardından gerektiği şekilde dahil etmeniz / genişletmeniz gerekir.
ben_h

13
Teşekkürler @Mike, yaptıklarını yapacağım, neden kötü olduğuna dair bir açıklama görmek güzeldi, cevabı kaldırmadığın için teşekkürler.
pupeno

sadece bir modül yüklemek istiyorsanız 'mymodule' eklemeye ne dersiniz?
Mike

1
@ben_h requireRails uygulamasında herhangi bir yerden olmamalı mısınız ? Bir tırmık görevi Şu anda ediyorum require-ing ve includeyaşayan bir modül -Ing lib/. Bunu yapmamalı mıyım?
Dennis

@ben_h Arama göstermektedir ki, 's ortak requiresenin lib/koduna (örneğin bu blog yazısı , bu SO cevap ). Hala her şeyden emin değilim. Kullanmama iddiasının arkasında daha fazla kanıt verebilir misiniz require?
Dennis

2

Dosya adını doğru heceleyin.

Ciddi anlamda. Sınıf Yönetişim :: ArchitectureBoard olduğu ve dosya lib / yönetişim / architecture_baord.rb ("tahta" ya aktarılan O ve A) olduğu için bir saat boyunca bir sınıfla savaştım

Geçmişe bakıldığında bariz görünüyor, ama bunu izleyen şeytan buydu. Sınıf, Rails'in sınıf adının mungingine dayalı olmasını beklediği dosyada tanımlanmamışsa, onu bulamaz.


2

İtibariyle Rails 5, uygulama dizin altında lib klasörü koymak veya yerine oluşturmak diğer anlamlı isim alanlarının yanı klasör için tavsiye edilir services, presenters, featuresvb ve raylar tarafından otomatik yükleme için uygulama dizininin altında koydu.

Lütfen bu GitHub Tartışma Bağlantısını da kontrol edin .


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.