2010-12-15 163 views
5

Dans mon application, jeComment faire référence au "chemin complet" d'un sous-module dans ruby?

VeryUniqueModule::Foo 
# and… 
VeryUniqueModule::Bar 

Foo et Bar sont chacun pour un autre service. Une partie de mon application doit comprendre dynamiquement quel module pour désigner, ce qu'il fait habilement comme ceci:

def service_api 
    # @relevant_object.service is a string that is either 'Foo' or 'Bar' 
    VeryUniqueModule.const_get(@relevant_object.service) 
end 

reparlerons plus loin.

Je viens de mettre à jour une bibliothèque, et elle a maintenant sa propre classe Foo de niveau supérieur (ce qui est une mauvaise conception de sa part). Maintenant, quand j'essaie d'invoquer @relevant_object.service_api::A_CONSTANT, mon application se plaint que de la bibliothèqueFoo n'a pas A_CONSTANT.

Retour à service_api ci-dessus - Je pensais que const_get retournait la classe elle-même. En fait, je le sais. Si je le lance dans irb tout est comme prévu - la valeur de retour est la classe elle-même, et je peux invoquer des choses sur la classe. Donc ...

  1. Comment est-il possible qu'il y ait un conflit d'espace de noms en premier lieu? Je cherche A_CONSTANT sur le objet de classe retourné par service_api, pas sur une chaîne que je suis eval ing ou quelque chose de génial comme ça - il ne devrait y avoir aucun problème d'espace de noms, je me réfère directement à un objet !
  2. Si c'est effectivement un problème, comment puis-je corriger service_api afin qu'il renvoie le chemin complet, «erm»?
+0

Ce que vous faites semble bien. Il y a probablement une erreur ailleurs. –

Répondre

0

Vous pouvez essayer ceci:

VeryUniqueModule.const_get('::VeryUniqueModule::' + @relevant_object.service) 

Et si cela ne fonctionne pas, vous pouvez essayer de contourner service_api et faire cela chaque fois que vous avez besoin A_CONSTANT:

Object.const_get('::VeryUniqueModule::' + @relevant_object.service + '::A_CONSTANT') 

Notez le :: avant VeryUniqueModule. Je ne pense pas que ce soit strictement nécessaire dans ce cas, mais cela pourrait être utile car cela garantit que Ruby recherchera VeryUniqueModule dans l'espace de noms global et non dans un autre module.

+0

Rien de tout cela ne fonctionnera. 'const_get' n'accepte que le nom de constante, tout' :: 'doit être traité d'une autre manière. E.g .: 'classe A; B = 42; fin; Object.const_get ("A :: B") # => NameError: nom de constante incorrect A :: B' –