2
votes

Les modules Rails sont en conflit avec les noms de classe de modèle

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.


0 commentaires

3 Réponses :


3
votes

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.


0 commentaires

3
votes

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.


3 commentaires

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



0
votes

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


0 commentaires