Chargement automatique des fichiers lib dans Rails 4

J’utilise la ligne suivante dans un initialiseur pour charger automatiquement du code dans mon répertoire /lib pendant le développement:

config / initializers / custom.rb:

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

(de Rails 3 Quicktip: rechargement automatique des dossiers lib en mode développement )

Cela fonctionne très bien, mais il est trop inefficace pour être utilisé en production. Au lieu de charger des bibliothèques à chaque requête, je veux juste les charger au démarrage. Le même blog a un autre article décrivant comment faire ceci:

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/**/"] 

Cependant, lorsque je passe à cela, même en développement, je reçois NoMethodErrors lorsque j’essaie d’utiliser les fonctions lib.

Exemple d’un de mes fichiers 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 

L’appel Time.milli_stamp lancera NoMethodError

Je me rends compte que d’autres ont répondu à des questions similaires sur SO, mais ils semblent tous avoir affaire à des conventions de nommage et à d’autres problèmes dont je ne devais pas me préoccuper. au chargement par démarrage . Quelle est la bonne façon de faire cela?

Je pense que cela peut résoudre votre problème:

  1. dans config / application.rb :

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

    et conservez la bonne convention de nommage dans lib .

    dans lib / foo.rb :

     class Foo end 

    dans lib / foo / bar.rb :

     class Foo::Bar end 
  2. Si vous voulez vraiment faire des patchs de singe dans un fichier comme lib / extensions.rb , vous pouvez le demander manuellement:

    dans config / initializers / require.rb :

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

PS

  • Rails 3 Modules / Classes Autoload par Bill Harding.

  • Et pour comprendre ce que fait exactement Rails en matière de chargement automatique?
    lire le chargement automatique de Rails - comment cela fonctionne, et quand ce n'est pas le cas par Simon Coffey.

Bien que cela ne réponde pas directement à la question, mais je pense que c’est une bonne alternative pour éviter complètement la question.

Pour éviter tous les eager_load_paths autoload_paths ou eager_load_paths , créez un eager_load_paths “lib” ou “misc” dans le répertoire “app”. Placez les codes comme vous le feriez normalement, et Rails chargera les fichiers comme le chargement (et le rechargement) des fichiers de modèle.

Cela pourrait aider quelqu’un comme moi à trouver cette réponse lors de la recherche de solutions à la manière dont Rails gère le chargement de la classe … J’ai trouvé que je devais définir un module dont le nom correspondait bien à mon nom plutôt que de définir une classe:

Dans le fichier lib / development_mail_interceptor.rb (oui, j’utilise du code d’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 

fonctionne, mais il ne se charge pas si je n’ai pas mis la classe dans un module.

Utilisez config.to_prepare pour vous charger des patchs / extensions de singe pour chaque requête en mode développement.

 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" 

fin