How to instantiate class from name string in Rails?
Ruby on-RailsRuby on-Rails-3StringClassInstantiationRuby on-Rails Problem Overview
How we can instantiate class from it's name string in Ruby-on-Rails?
For example we have it's name in database in format like "ClassName" or "my_super_class_name".
How we can create object from it?
Solution:
Was looking for it myself, but not found, so here it is. Ruby-on-Rails API Method
name = "ClassName"
instance = name.constantize.new
It can be even not formatted, we can user string method .classify
name = "my_super_class"
instance = name.classify.constantize.new
Of course maybe this is not very 'Rails way', but it solves it's purpose.
Ruby on-Rails Solutions
Solution 1 - Ruby on-Rails
klass = Object.const_get "ClassName"
about class methods
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
Solution 2 - Ruby on-Rails
Others may also be looking for an alternative that does not throw an error if it fails to find the class. safe_constantize
is just that.
class MyClass
end
"my_class".classify.safe_constantize.new # #<MyClass:0x007fec3a96b8a0>
"omg_evil".classify.safe_constantize.new # nil
Solution 3 - Ruby on-Rails
You can simply convert a string and initialize a class out of it by:
klass_name = "Module::ClassName"
klass_name.constantize
To initialize a new object:
klass_name.constantize.new
I hope this turns out to be helpful. Thanks!
Solution 4 - Ruby on-Rails
I'm surprised nobody is considering security and hacking in their responses. Instantiation of an arbitrary string that likely came even indirectly from user input is asking for trouble and hacking. We all should/must be whitelisting unless we're sure the string is fully controlled and monitored
def class_for(name)
{
"foo" => Foo,
"bar" => Bar,
}[name] || raise UnknownClass
end
class_for(name_wherever_this_came_from).create!(params_somehow)
How you would know the appropriate params arbitrarily without having a whitelist would be challenging but you get the idea.