2010-08-12 7 views
62

Comment appeler une classe à partir d'une chaîne contenant ce nom de classe à l'intérieur? (Je suppose que je pourrais faire cas/quand mais cela semble moche.)ruby ​​convertir le nom de classe en chaîne en classe

La raison pour laquelle je demande est parce que j'utilise le plugin acts_as_commentable, entre autres, et ceux-ci stockent le commentable_type comme une colonne. Je veux pouvoir appeler n'importe quelle classe commentable pour y faire un find(commentable_id).

Merci.

Répondre

90

Je pense que ce que vous voulez est constantize

C'est une construction de RoR. Je ne sais pas s'il y a un pour le cœur de rubis

+0

parfait, c'est exactement ce que je cherchais. – unsorted

+33

Pour Ruby, vous utiliseriez 'Module.const_get'. L'avantage de 'constantize' est qu'il fonctionne même avec des espaces de noms profondément imbriqués, donc vous pouvez faire' 'Functional :: Collections :: LazyList'.constantize' et obtenir la classe LazyList depuis le module Collections dans le module Functional, alors qu'avec' const_get', vous devriez faire quelque chose comme ''Functional :: Collections :: LazyList'.split (' :: '). reduce (Module,: const_get)'. – Chuck

32
"Object".constantize # => Object 
+1

+1 car il était simultané – unsorted

25

d'une chaîne, premier appel classify pour créer un nom de classe (encore une chaîne), puis appelez constantize pour essayer de trouver et de retourner la constante de nom de classe (notez que class names are constants).

some_string.classify.constantize 
+6

Vous devriez utiliser camelize au lieu de classifier puisque classify est pour les noms de table et ne gère pas très bien la pluralisation. –

+1

Merci! c'est génial! – duykhoa

+2

Votre réponse est vraiment précieuse, mais vous devriez utiliser "titleize" pour le nom de la table qui inclut par l'espace, et supprimer l'espace blanc de la chaîne pour donner un sens au nom complet de la classe. – SSR

3

Si vous voulez convertir la chaîne à actuall nom de classe modèle d'accès ou de toute autre classe

str = "group class" 

> str.camelize.constantize 'or' 
> str.classify.constantize 'or' 
> str.titleize.constantize 

Example : 
    def call_me(str) 
    str.titleize.gsub(" ","").constantize.all 
    end 

Call method : call_me("group class") 

Result: 
    GroupClass Load (0.7ms) SELECT `group_classes`.* FROM `group_classes` 
3

Lorsque ActiveSupport est disponible (par exemple dans Rails): String#constantize ou String#safe_constantize, qui est "ClassName".constantize.

En pur Ruby: Module#const_get, typiquement Object.const_get("ClassName").

Dans les rubis récents, les deux fonctionnent avec des constantes imbriquées dans des modules, comme dans Object.const_get("Outer::Inner").

7

Je sais que c'est une vieille question mais je veux juste laisser cette note, elle peut être utile pour d'autres.

En mode Ruby, Module.const_get peut trouver des constantes imbriquées. Par exemple, ayant la structure suivante:

module MyModule 
    module MySubmodule 
    class MyModel 
    end 
    end 
end 

Vous pouvez l'utiliser comme suit:

Module.const_get("MyModule::MySubmodule::MyModel") 
MyModule.const_get("MySubmodule") 
MyModule::MySubmodule.const_get("MyModel") 
Questions connexes