J'ai mis à niveau l'une de mes applications de Rails 4.2.6 à Rails 5.0.0. Le Guide de mise à nivea indique que la fonctionnalité de chargement automatique est maintenant désactivée en production par défaut.
Maintenant, je reçois toujours une erreur sur mon serveur de production puisque je charge tous les fichiers lib avec autoload dans le fichier application.rb
.
module MyApp
class Application < Rails::Application
config.autoload_paths += %W( lib/ )
end
end
Pour l'instant, j'ai réglé le config.enable_dependency_loading
sur true
mais je me demande s'il existe une meilleure solution à ce problème. Il doit y avoir une raison pour laquelle le chargement automatique est désactivé en production par défaut.
Le chargement automatique est désactivé dans l'environnement de production pour des raisons de sécurité des threads. Merci à @ Зелёный pour le lien.
J'ai résolu ce problème en stockant les fichiers lib dans un dossier lib
de mon répertoire app
, comme recommandé sur Github . Chaque dossier du dossier app
est chargé automatiquement par Rails.
Ma liste de modifications après le passage à Rails 5:
lib
dir dans app
car tout le code dans l'application est automatiquement chargé dans dev et . eager chargé dans prod et surtout est auto-chargé en développement, vous n'avez donc pas besoin de redémarrer le serveur à chaque fois faire des changements.require
pointant vers vos propres classes dans lib
car elles sont toutes auto-chargées de toute façon si leur nom de fichier/répertoire est correct et si vous laissez require
instructions, le chargement automatique peut être interrompu. Plus d'infos iciconfig.eager_load = true
dans tous les environnements pour voir les problèmes de chargement de code avec impatience dans dev.Rails.application.eager_load!
avant de jouer avec les threads pour éviter les erreurs de "dépendance circulaire".Si vous avez des extensions Ruby/Rails, laissez ce code dans l'ancien répertoire lib
et chargez-le manuellement à partir de l'initialiseur. Cela garantira que les extensions sont chargées avant votre logique supplémentaire qui peut en dépendre:
# config/initializers/extensions.rb
Dir["#{Rails.root}/lib/Ruby_ext/*.rb"].each { |file| require file }
Dir["#{Rails.root}/lib/Rails_ext/*.rb"].each { |file| require file }
Je viens d'utiliser config.eager_load_paths
au lieu de config.autoload_paths
comme mention akostadinov sur le commentaire github: https://github.com/Rails/rails/issues/13142#issuecomment-27549207
# config.autoload_paths << Rails.root.join('lib')
config.eager_load_paths << Rails.root.join('lib')
Cela fonctionne sur l'environnement de développement et de production.
Merci Johan pour la suggestion de remplacer #{Rails.root}/lib
par Rails.root.join('lib')
!
Il doit y avoir une raison pour laquelle le chargement automatique est désactivé en production par défaut.
Voici une longue discussion sur cette question. https://github.com/Rails/rails/issues/13142
Cela permet d’avoir le chargement automatique de lib et fonctionne aussi dans l’environnement de production.
P.S. J'ai changé ma réponse. Elle ajoute maintenant aux chemins désirés, un chemin de chargement automatique, quel que soit l'environnement, pour permettre également de travailler dans des environnements personnalisés (comme la scène).
# config/initializers/load_lib.rb
...
config.eager_load_paths << Rails.root.join('lib')
config.autoload_paths << Rails.root.join('lib')
...
En un sens, il existe une approche unifiée dans Rails 5 pour centraliser la configuration de chargement rapide et de chargement automatique, tout en ajoutant le chemin de chargement automatique requis chaque fois que la charge de chargement rapide est configurée, sinon elle ne pourra pas fonctionner correctement:
# config/application.rb
...
config.paths.add Rails.root.join('lib').to_s, eager_load: true
# as an example of autoload only config
config.paths.add Rails.root.join('domainpack').to_s, autoload: true
...
Pour qui que ce soit qui a du mal comme moi, il ne suffit pas de placer un répertoire sous app/
. Oui, vous obtiendrez un chargement automatique mais pas nécessaire rechargement, ce qui nécessite de respecter les conventions de nommage .
De plus, l’utilisation d’initializer pour charger l’ancien niveau de racine lib
empêchera le rechargement pendant le développement.
Déplacer le dossier lib vers une application aidant à résoudre un problème, mon API Twitter ne fonctionnerait pas en production. J'avais "TwitterApi constante constante non initialisée" et mon API Twitter était dans mon dossier lib. J'avais config.autoload_paths += Dir["#{Rails.root}/app/lib"]
dans mon application.rb mais cela ne fonctionnait pas avant de déplacer le dossier.
Cela a fait le tour
pour résumer la réponse de Lev: mv lib app
suffisait pour que tout mon code lib
soit auto-chargé/rechargé automatiquement.
(Rails 6.0.0beta3 mais devrait fonctionner correctement sur Rails 5.x aussi)