Dans notre application Rails, nous avons quelques modèles comme:
TypeError: StoreBuild is not a module
Et puis nous avons des ouvriers comme:
ProductName::StoreBuild::StoreBuildWorker.perform_async(@store_build.id)
Nous appelons ensuite ces travailleurs aiment:
module ProductName module StoreBuild class StoreBuildWorker end end end
Cependant, nous avons parfois rencontré une erreur:
module ProductName class StoreBuild end end
Lorsque nous inspectons le StoreBuild à partir de ce dernier line it, il pense que c'est la classe modèle et non le module worker que nous référencons qui est à l'origine de l'erreur ...
Comment arrêtez-vous les modules en conflit avec les noms de classe?
Rails n'utilise pas d'espaces de noms pour les dossiers de niveau supérieur, cela signifie donc que les modèles et les travailleurs qui souhaitent utiliser les mêmes espaces de noms sont en conflit car ils n'ont eux-mêmes aucun espace de noms.
3 Réponses :
Je suppose que parce qu'ils sont tous les deux dans le même espace de noms, vous ne pouvez pas leur donner le même nom. Essayez de changer le nom du module de StoreBuild
à autre chose. Cela devrait résoudre votre problème. partagerait plus de documents à ce sujet.
Cela échoue en raison de la hiérarchie de chargement automatique de Rails. Faites le point sur Constantes de chargement et de rechargement automatiques pour voir comment cela fonctionne.
Rails voit ProductName :: StoreBuild
, puis met en cache sa référence en tant que classe et non en tant que module. Lorsque vous avez alors ProductName :: StoreBuild :: StoreBuildWorker
, il dit "hein, c'est un module maintenant" et panique.
Anecdotique: votre application est probablement très bien organisée.
Alors disons-nous que vous ne pouvez pas avoir un module et un modèle avec le même nom sous le même module?
Non. Rails ne veut qu'un seul type de nom par objet (module, classe). Habituellement, ce que je fais est de mettre au pluriel pour les modules avec des noms similaires, tels que ProductName :: StoreBuild :: StoreBuildWorker
deviendrait ProductName :: StoreBuilds :: StoreBuildWorker
. Ce n'est pas le plus joli, mais ça fait passer le message.
@Cameron Il s'agit de Ruby plus que spécifiquement des rails. Il s'agit d'un conflit de dénomination car une classe Module est Module et une classe Class est Classe. S'ils étaient dans des espaces de noms différents, cela serait acceptable, mais pas dans le même espace de noms. Cela étant dit, rien ne vous empêche de déclarer StoreBuildWorker
dans la classe StoreBuild
Le message d'erreur vous indique qu'il y a un conflit puisque vous redéfinissez ProductName :: StoreBuild
comme un module où vous avez précédemment défini la même chose en tant que classe.
Si vous ne le faites pas Je ne veux rien renommer, vous pouvez imbriquer des modules dans une classe si cela a du sens dans l'espacement des noms de votre application.
Donc, si vous avez une classe:
module ProductName class StoreBuild class StoreBuildWorker end end end