J'utilise la ligne suivante dans un initialiseur pour charger automatiquement le 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 astuce rapide Rails 3: recharger automatiquement les dossiers de lib en mode de développement )
Cela fonctionne très bien, mais son utilisation en production est trop inefficace. Au lieu de charger des bibliothèques à chaque requête, je veux simplement les charger au démarrage. Le même blog a n autre article décrivant comment faire cela:
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, j'obtiens 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 de Time.milli_stamp
lancera NoMethodError
Je me rends compte que d'autres ont répondu à des questions similaires sur SO, mais ils semblent tous traiter de conventions de dénomination et d'autres problèmes sur lesquels je n'avais pas à m'inquiéter auparavant- Mes classes de bibliothèque travaillé pour le chargement par requête, je veux juste le changer en - démarrage . Quelle est la bonne façon de faire cela?
Je pense que cela peut résoudre votre problème:
dans config/application.rb :
config.autoload_paths << Rails.root.join('lib')
et conservez la bonne convention d'appellation dans lib .
dans lib/foo.rb :
class Foo
end
dans lib/foo/bar.rb :
class Foo::Bar
end
si vous voulez vraiment faire quelques 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"
P.S.
Modules/classes à chargement automatique Rails par Bill Harding.
Et pour comprendre ce que Rails fait exactement avec le chargement automatique?
read Chargement automatique de Rails - Comment ça marche et quand ça ne marche pas 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 tracas autoload_paths
ou eager_load_paths
, créez un répertoire "lib" ou "misc" sous le répertoire "app". Placez les codes comme vous le feriez normalement ici, et Rails chargera les fichiers de la même manière que la manière dont ils chargeront (et rechargeront) les fichiers de modèle.
Cela pourrait aider quelqu'un comme moi qui trouve cette réponse à la recherche de solutions à la manière dont Rails gère le chargement de la classe ... J'ai constaté que je devais définir un module
dont le nom correspond à mon nom de fichier, plutôt que de simplement définir une classe:
Dans le fichier lib/development_mail_interceptor.rb (Oui, j'utilise le code d'un Railscast :))
module DevelopmentMailInterceptor
class DevelopmentMailInterceptor
def self.delivering_email(message)
message.subject = "intercepted for: #{message.to} #{message.subject}"
message.to = "[email protected]"
end
end
end
fonctionne, mais cela ne se charge pas si je n’avais pas mis la classe dans un module.
Utilisez config.to_prepare pour charger vos correctifs/extensions Monkey pour chaque requête en mode de 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