web-dev-qa-db-fra.com

Rails 5: Charger des fichiers lib en production

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.

108
Tobias

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.

29
Tobias

Ma liste de modifications après le passage à Rails 5:

  1. Placez 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.
  2. Supprimez toutes les instructions 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 ici
  3. Définissez config.eager_load = true dans tous les environnements pour voir les problèmes de chargement de code avec impatience dans dev.
  4. Utilisez Rails.application.eager_load! avant de jouer avec les threads pour éviter les erreurs de "dépendance circulaire".
  5. 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 }
    
140
Lev Lukomsky

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')!

64
Michał Zalewski

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

20
Зелёный

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')
...
11
srghma

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
...
4
pocheptsov

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.

2
Abdullah Barrak

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

0
Laurie

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)

0
localhostdotdev