Caricamento automatico dei file lib in Rails 4

Io uso la seguente riga in un inizializzatore per caricare automaticamente il codice nella mia directory /lib durante lo sviluppo:

config / inizializzatori / custom.rb:

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

(da Rails 3 Quicktip: Auto ricarica le cartelle lib in modalità sviluppo )

Funziona alla grande, ma è troppo inefficiente da usare in produzione. Invece di caricare le librerie su ogni richiesta, voglio solo caricarle all’avvio. Lo stesso blog ha un altro articolo che descrive come fare questo:

config / application.rb:

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

Tuttavia, quando passo a questo, anche in fase di sviluppo, ottengo NoMethodErrors quando provo ad usare le funzioni lib.

Esempio di uno dei miei file lib:

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 

Calling Time.milli_stamp genererà NoMethodError

Mi rendo conto che altri hanno risposto a domande simili su SO, ma sembrano trattare tutte le convenzioni di denominazione e altri problemi di cui non dovevo preoccuparmi prima- Le mie classi lib hanno già funzionato per il caricamento per richiesta, voglio solo cambiarlo al caricamento all’avvio . Qual è il modo giusto per farlo?

Penso che questo possa risolvere il tuo problema:

  1. in config / application.rb :

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

    e mantieni la giusta convenzione di denominazione in lib .

    in lib / foo.rb :

     class Foo end 

    in lib / foo / bar.rb :

     class Foo::Bar end 
  2. se vuoi davvero fare alcune patch per le scimmie in file come lib / extensions.rb , puoi richiederlo manualmente:

    in config / initializers / require.rb :

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

PS

  • Rails 3 moduli / classi di caricamento automatico di Bill Harding.

  • E per capire cosa fa esattamente Rails in merito al caricamento automatico?
    leggi l' autoloading di Rails: come funziona e quando non lo fa Simon Coffey.

Anche se questo non risponde direttamente alla domanda, ma penso che sia una buona alternativa per evitare del tutto la domanda.

Per evitare tutti i problemi di autoload_paths o eager_load_paths , creare una directory “lib” o “misc” nella directory “app”. Inserisci i codici come faresti normalmente lì e Rails caricherà i file proprio come caricheranno (e ricaricheranno) i file dei modelli.

Questo potrebbe aiutare qualcuno come me che trova questa risposta quando cerca soluzioni a come Rails gestisce il caricamento della class … Ho scoperto che dovevo definire un module cui nome corrispondesse al mio nome in modo appropriato, piuttosto che definire una class:

Nel file lib / development_mail_interceptor.rb (Sì, sto usando il codice da un Railscast :))

 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 

funziona, ma non si carica se non avessi inserito la class in un modulo.

Usa config.to_prepare per caricare patch / estensioni scimmia per ogni richiesta in modalità sviluppo.

 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" 

fine