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.
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
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
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!
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.