Lib dosyalarını otomatik yükleme in Rails 4


229

/libGeliştirme sırasında dizinimdeki kodu otomatik olarak yüklemek için bir başlatıcıda aşağıdaki satırı kullanıyorum :

config / ilklendiriciler / custom.rb:

RELOAD_LIBS = Dir[Rails.root + 'lib/**/*.rb'] if Rails.env.development?

( Rails 3 Quicktip'ten: Geliştirme modunda lib klasörlerini otomatik olarak yeniden yükle )

Harika çalışıyor, ancak üretimde kullanmak için çok verimsiz - Her istek üzerine libs yüklemek yerine, sadece başlangıçta bunları yüklemek istiyorum. Aynı blogda bunun nasıl yapılacağını açıklayan başka bir makale var :

config / application.rb:

# Custom directories with classes and modules you want to be autoloadable.
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]

Ancak, buna geçiş yaptığımda, geliştirme aşamasında bile, lib fonksiyonlarını kullanmaya çalışırken NoMethodErrors alıyorum.

Lib dosyalarımdan birine örnek:

lib / extensions.rb:

Time.class_eval do
  def self.milli_stamp
    Time.now.strftime('%Y%m%d%H%M%S%L').to_i
  end
end

Arayan Time.milli_stampNoMethodError atacağım

Başkalarının SO ile ilgili benzer soruları yanıtladığını fark ettim ama hepsi daha önce endişelenmem gereken adlandırma kuralları ve diğer konularla ilgileniyor gibi görünüyor - Lib derslerim zaten istek başına yükleme için çalıştı , sadece değiştirmek istiyorum per- için başlangıç yükleme. Bunu yapmanın doğru yolu nedir?


Rails uygulaması başlatıldığında config / initializers klasörü otomatik olarak yüklenir mi?
Jwan622

Yanıtlar:


548

Bunun sorununuzu çözebileceğini düşünüyorum:

  1. içinde config / application.rb :

    config.autoload_paths << Rails.root.join('lib')

    ve doğru adlandırma kuralını lib'de saklayın .

    içinde lib / foo.rb :

    class Foo
    end

    içinde lib / foo / bar.rb :

    class Foo::Bar
    end
  2. Gerçekten lib / extensions.rb gibi bazı maymun yamalarını yapmak istiyorsanız, manuel olarak isteyebilirsiniz:

    içinde config / ilklendiriciler / require.rb :

    require "#{Rails.root}/lib/extensions" 

PS


1
@ ifyouseewendy- Tam haklısınız - extensions.rb , Rails adlandırma kurallarına uymadığı için Rails, yükleme işlemine dahil etmez. Elle gerektirerek çalıştım.
Yarin

@ ifyouseewendy Modeller yüklenmeden önce dosyaları nasıl ekleyebilirim? otomatik yükleme yolunu ekleyin, ama dahil etme sırasını nasıl kontrol edebilirsiniz? thx
Matrix

@Matrix "modeller yüklenmeden önce dosyaları dahil et", otomatik yükleme özelliğini kullanmadan dosyanızı manuel olarak isteyebilirsiniz.
ifyouseewendy

Başlatıcıda gerekiyorsa ancak dosya autoload_path içinde ise @ifyouseewendy, yeniden yüklenecek (2 kez yüklendi) veya değil mi? theire php gibi bir "requir_once" dir?
Matrix

5
Bu, Rails 5 API'sinin üretimde işe yaramadığı görülüyor (ancak geliştirme aşamasında). Kullanmanız gerektiğine inanıyorum config.eager_load_paths << Rails.root.join('lib'). Ancak, eager_load_pathsgörevlerde de her şeyi yükleyen önemli bir dezavantajı var . Bence lulalala'nın çözümü daha iyi. İşte daha fazla ayrıntı içeren bir blog yazısı: blog.arkency.com/2014/11/…
hirowatari

33

Bu soruya doğrudan cevap vermese de, soruyu tamamen önlemek için iyi bir alternatif olduğunu düşünüyorum.

Tüm autoload_pathsveya eager_load_pathszorluklardan kaçınmak için , "app" dizini altında bir "lib" veya "misc" dizini oluşturun. Kodları normalde oraya yaptığınız gibi yerleştirin ve Rails dosyaları tıpkı model dosyalarını nasıl yükleyeceği (ve yeniden yükleyeceği gibi) yükleyecektir.


3
Rails 4.2'deyim. ve otomatik olarak altında dosyaları yüklemez app, ben elle yapmak gerekir ...... veya autload yolu koymak gerekir ..
Arup

6
Yanılıyorsunuz, Arup, uygulama dizininin alt dizinleri otomatik olarak Rails 4.2'deki autoload_paths dizisindedir. Edgeguides.rubyonrails.org/…
Dr.Strangelove

Eklenmeyen app/viewsdizin hariç ; veya açıkça kaldırılır.
James B. Byrne

1
Mükemmel cevap. Raylar 5 / api benim için işe yarayan tek şey.
jstafford

6
Bunun libbirden fazla projeye uygulanabilen ve muhtemelen bir gem'e çıkarılabilecek kodlar için olduğunu unutmayın . Değilse olarak uygulama arama altında daha uygun bir klasör oluşturmak services/veya presenters/bu kapalı ve hatta subdirs.
PhilT

6

Bu, Rails'in sınıf yüklemesini nasıl ele aldığına dair çözümler ararken benim gibi birisine yardımcı olabilir ... moduleSadece bir sınıf tanımlamak yerine, dosya adımla uygun bir şekilde bir ad tanımlamak zorunda kaldım :

Lib / development_mail_interceptor.rb dosyasında (Evet, Railscast kodunu kullanıyorum :))

module DevelopmentMailInterceptor
  class DevelopmentMailInterceptor
    def self.delivering_email(message)
      message.subject = "intercepted for: #{message.to} #{message.subject}"
      message.to = "myemail@mydomain.org"
    end
  end
end

çalışır, ancak sınıfı bir modülün içine koymamış olsaydım yüklenmez.


1
Ruby'de "uygun şekilde eşleştirme", dosyanın Ruby sisteminde (Rails durumunda autoload_paths) kullanılan yükleme yollarında LOAD_PATH/module/class.rbolduğu (alt çizgi) dosya sisteminde bulunduğu anlamına gelir LOAD_PATH. lib, Rails tarafından otomatik yüklenmekten otomatik yüklenmemeye dalmış ve son sürümlerde (> = Rails 3.x) otomatik yüklenmemiştir. Bu işi sizin için yapan sihir ne olursa olsun önerilmez. Belki de eski bir Railscast?
Peter H. Boling

0

Geliştirme modunda her istek için maymun yamalarını / uzantılarını yüklemek için config.to_prepare komutunu kullanın.

config.to_prepare do |action_dispatcher|
 # More importantly, will run upon every request in development, but only once (during boot-up) in production and test.
 Rails.logger.info "\n--- Loading extensions for #{self.class} "
 Dir.glob("#{Rails.root}/lib/extensions/**/*.rb").sort.each do |entry|
   Rails.logger.info "Loading extension(s): #{entry}"
   require_dependency "#{entry}"
 end
 Rails.logger.info "--- Loaded extensions for #{self.class}\n"

son

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.