web-dev-qa-db-fra.com

Comment instancier une classe à partir d'une chaîne de nom dans Rails?

Comment pouvons-nous instancier une classe à partir de sa chaîne de nom dans Ruby-on-Rails?

Par exemple, nous avons son nom dans la base de données dans un format comme "ClassName" ou "my_super_class_name".

Comment pouvons-nous en créer un objet?

Solution:

Je le cherchais moi-même, mais je ne l'ai pas trouvé, alors le voici. Méthode API Ruby-on-Rails

name = "ClassName"
instance = name.constantize.new  

Il peut même ne pas être formaté, nous pouvons utiliser la méthode chaîne de caractères . Classify

name = "my_super_class"
instance = name.classify.constantize.new

Bien sûr, ce n'est peut-être pas très "Rails Way", mais cela résout son objectif.

67
klass = Object.const_get "ClassName"

sur les méthodes de classe

class KlassExample
    def self.klass_method
        puts "Hello World from Class method"
    end
end
klass = Object.const_get "KlassExample"
klass.klass_method

irb(main):061:0> klass.klass_method
Hello World from Class method
71
Eugene Rourke

D'autres peuvent également rechercher une alternative qui ne génère pas d'erreur si elle ne trouve pas la classe. safe_constantize c'est juste ça.

class MyClass
end

"my_class".classify.safe_constantize.new #  #<MyClass:0x007fec3a96b8a0>
"omg_evil".classify.safe_constantize.new #  nil 
33
maninalift

Vous pouvez simplement convertir une chaîne et en initialiser une classe en:

klass_name = "Module::ClassName"
klass_name.constantize

Pour initialiser un nouvel objet:

klass_name.constantize.new

J'espère que cela s'avère utile. Merci!

6
Pushp Raj Saurabh

Je suis surpris que personne n'envisage la sécurité et le piratage dans leurs réponses. L'instanciation d'une chaîne arbitraire qui est probablement venue même indirectement de l'entrée utilisateur demande des problèmes et du piratage. Nous devrions tous/devons être sur liste blanche, sauf si nous sommes sûrs que la chaîne est entièrement contrôlée et surveillée

def class_for(name)
  {
    "foo" => Foo,
    "bar" => Bar,
  }[name] || raise UnknownClass
end

class_for(name_wherever_this_came_from).create!(params_somehow)

Comment vous pourriez connaître arbitrairement les paramètres appropriés sans avoir une liste blanche serait difficile, mais vous avez l'idée.

3
RubesMN