web-dev-qa-db-fra.com

Meilleur moyen de charger le module/la classe à partir du dossier lib dans Rails 3?

Puisque la dernière version de Rails 3 ne charge plus automatiquement les modules et les classes depuis lib, Quel serait le meilleur moyen de les charger?

De github:

A few changes were done in this commit:

Do not autoload code in *lib* for applications (now you need to explicitly 
require them). This makes an application behave closer to an engine 
(code in lib is still autoloaded for plugins);
268
Vincent

A partir de Rails 2.3.9 , il existe un paramètre dans config/application.rb dans lequel vous pouvez spécifier des répertoires contenant des fichiers que vous souhaitez charger automatiquement.

De application.rb:

# Custom directories with classes and modules you want to be autoloadable.
# config.autoload_paths += %W(#{config.root}/extras)
248
Slobodan Kovacevic
# Autoload lib/ folder including all subdirectories
config.autoload_paths += Dir["#{config.root}/lib/**/"]

Source: Rails 3 Quicktip: répertoire de chargement automatique lib incluant tous les sous-répertoires, évitez le chargement paresseux

Veuillez noter que les fichiers contenus dans le dossier lib ne sont chargés qu'au démarrage du serveur. Si vous voulez avoir la possibilité de charger automatiquement ces fichiers, lisez: Rails 3 Aide rapide: recharger automatiquement les dossiers de lib en mode de développement . Sachez que cela n'est pas destiné à un environnement de production, car le rechargement permanent ralentit la machine.

196
thankful

La magie de l'autoloading

Je pense que la possibilité de contrôler les dossiers à partir desquels le chargement automatique est effectué a été suffisamment couverte dans les autres réponses. Cependant, si quelqu'un a des problèmes de chargement alors que son chemin de chargement automatique a été modifié, alors cette réponse tente d'expliquer quelle est la magie derrière ce processus de chargement automatique.

Donc, quand il s'agit de charger des choses à partir de sous-répertoires, il faut savoir qu'il existe une convention ou une convention. Parfois, la magie de Ruby/Rails (cette fois principalement Rails) peut rendre difficile de comprendre pourquoi quelque chose se passe. Tout module déclaré dans les chemins de chargement automatique ne sera chargé que si le nom du module correspond au nom du répertoire parent. Donc, si vous essayez de mettre dans lib/my_stuff/bar.rb quelque chose comme:

module Foo
  class Bar
  end
end

Il ne sera pas chargé automatiquement. Puis à nouveau si vous renommez le répertoire parent en foo, hébergeant ainsi votre module sur chemin: lib/foo/bar.rb. Ce sera là pour vous. Une autre option consiste à nommer le fichier à charger automatiquement en fonction du nom du module. Il est évident qu’il ne peut y avoir qu’un seul fichier portant ce nom. Au cas où vous auriez besoin de scinder votre contenu en plusieurs fichiers, vous pouvez bien sûr utiliser ce fichier pour en demander d’autres, mais je ne le recommande pas, car lorsque vous êtes en mode de développement et que vous modifiez ces autres fichiers, Rails n’est pas en mesure de le faire automatiquement. rechargez-les pour vous. Mais si vous le souhaitez vraiment, vous pouvez avoir un fichier portant le nom du module, qui spécifie ensuite les fichiers requis pour utiliser le module. Donc, vous pourriez avoir deux fichiers: lib/my_stuff/bar.rb et lib/my_stuff/foo.rb et le premier étant le même que ci-dessus et le dernier contenant une seule ligne: require "bar" et qui fonctionnerait exactement de la même manière.

P.S. Je me sens obligé d'ajouter une chose plus importante. Dernièrement, chaque fois que je veux avoir quelque chose dans le répertoire lib qui doit être chargé automatiquement, j'ai tendance à penser que si c'est quelque chose que je développe en fait spécifiquement pour ce projet (ce qui est généralement le cas, cela pourrait un jour transformer en un "statique" extrait de code utilisé dans de nombreux projets ou un sous-module git, etc. Dans ce cas, il devrait absolument être dans le dossier lib) alors peut-être que sa place n’est pas du tout dans le dossier lib. Peut-être que cela devrait se trouver dans un sous-dossier sous le dossier de l'application · J'ai l'impression que c'est la nouvelle façon de faire Rails. De toute évidence, la même magie opère partout où vous insérez des trucs dans votre chemin de chargement automatique, donc c'est bon pour ces choses. Quoi qu'il en soit, ce ne sont que mes pensées sur le sujet. Vous êtes libre de ne pas être d'accord. :)


MISE À JOUR: À propos du type de magie ..

Comme plusieurs de ses collègues l'ont souligné dans son commentaire, le "mécanisme de chargement automatique d'un module" fait bien partie de Ruby, mais le chemin des chemins de chargement automatique ne l'est pas. Vous n'avez pas besoin de Rails pour faire autoload :Foo, File.join(Rails.root, "lib", "my_stuff", "bar"). Et lorsque vous essayez de référencer le module Foo pour la première fois, il est chargé pour vous. Cependant, Rails nous offre un moyen d'essayer de charger automatiquement des éléments à partir de dossiers enregistrés. Cette procédure a été implémentée de telle sorte que les conventions de dénomination doivent être respectées. Si cela n’avait pas été implémenté de la sorte, chaque fois que vous ferez référence à quelque chose qui n’a pas été chargé, il devra parcourir tous les fichiers de tous les dossiers à chargement automatique et vérifier si l’un d’eux contient ce que vous tentiez de référencer. Cela éliminerait l'idée de chargement automatique et de chargement automatique. Cependant, avec ces conventions en place, il est possible de déduire du module/de la classe que vous essayez de charger où cela pourrait être défini et de le charger.

81
Timo

Attention: si vous voulez charger le 'patch de singe' ou la 'classe ouverte' depuis votre dossier 'lib', n'utilisez pas l'approche 'autoload' !!! 

  • Approche " config.autoload_paths ": ne fonctionne que si vous chargez une classe définie uniquement à UN endroit. Si une classe a déjà été définie ailleurs, vous ne pouvez pas la charger à nouveau avec cette approche.

  • L'approche " config/initializer/load_rb_file.rb ": fonctionne toujours! quelle que soit la classe cible est une nouvelle classe ou une "classe ouverte" ou un "patch de singe" pour la classe existante, cela fonctionne toujours! 

Pour plus de détails, voir: https://stackoverflow.com/a/6797707/445908

41

Très similaire, mais je pense que c'est un peu plus élégant:

config.autoload_paths += Dir["#{config.root}/lib", "#{config.root}/lib/**/"]
28
Brian Armstrong

Dans mon cas, j'essayais simplement de charger un fichier directement sous le répertoire lib. 

Dans application.rb ...

require '/lib/this_file.rb' 

ne fonctionnait pas, même en console et puis quand j'ai essayé 

require './lib/this_file.rb' 

et Rails charge parfaitement le fichier. 

Je suis toujours assez noob et je ne sais pas pourquoi ça marche mais ça marche. Si quelqu'un veut bien me l'expliquer, je l'apprécierai: D J'espère que cela aidera quelqu'un de toute façon. 

14
Nick Res

J'ai eu le même problème. Voici comment je l'ai résolu. La solution charge le répertoire lib et tous les sous-répertoires (pas seulement le répertoire direct). Bien sûr, vous pouvez l'utiliser pour tous les répertoires.

# application.rb
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]
7
hjuskewycz

config.autoload_paths ne fonctionne pas pour moi. Je le résous d'une autre manière

Ruby on Rails 3 ne recharge pas automatiquement le code à partir du dossier/lib. Je le résous en mettant à l'intérieur ApplicationController

Dir["lib/**/*.rb"].each do |path|
  require_dependency path
end 
5
msa7

Si seuls certains fichiers ont besoin d'accéder aux modules de lib, ajoutez simplement une instruction require aux fichiers qui en ont besoin. Par exemple, si un modèle doit accéder à un module, ajoutez:

require 'mymodule'

en haut du fichier model.rb.

4
Mike Fischer

À partir de Rails 5, il est recommandé de placer le dossier lib dans le répertoire app ou de créer d'autres espaces de noms significatifs pour le dossier sous la forme services, presenters, features etc. et de le placer dans le répertoire app pour le chargement automatique par Rails.

Veuillez vérifier ceci GitHub Discussion Link ainsi.

2
Ashik Salman

Il y a plusieurs raisons pour lesquelles vous pourriez avoir des problèmes de chargement depuis lib - voir ici pour plus de détails - http://www.williambharding.com/blog/technology/Rails-3-autoload-modules-and-classes-in-production/

  • correction du chemin de chargement automatique
  • lié à threadsafe
  • nommant en relation
  • ...
1
Chris Kimpton

Épelle le nom de fichier correctement.  

Sérieusement. Je me suis battu avec une classe pendant une heure parce que la classe était Governance :: ArchitectureBoard et que le fichier était dans lib/Governance/architecture_baord.rb (O et A transposés dans "board")

Cela semble évident en rétrospective, mais c’est le diable qui l’a retrouvée. Si la classe n'est pas définie dans le fichier dans lequel Rails s'attend à ce qu'elle soit basée sur la modification du nom de la classe, elle ne le trouvera tout simplement pas. 

0
David Hempy