Reputation: 3111
Is there a way in Ruby to take a symbol or string and turn it into a class of the same name?
For instance, if I have a class such as
class Bob
def talk
puts "Hi, I'm bob"
end
end
And a method I have somewhere else in the code is passed a symbol :bob, can I in some way turn that into the class Bob? Maybe something like
b = :Bob.new
b.talk
Or is there a way to do something similar to this?
Upvotes: 39
Views: 20831
Reputation: 1001
For use with Rails only.
With a string:
"Module".constantize #=> Module
"Class".constantize #=> Class
With a symbol:
:module.to_s.classify.constantize #=> Module
:open_struct.to_s.classify.constantize #=> OpenStruct
If you are dealing with a multi-word symbol, then you'll want to add #classify
to the chain to properly handle the capitalization of all the parts of the constant.
http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-constantize
Upvotes: 45
Reputation: 289
in my case, both example below worked, but you also have not to forget namespace:
Object.const_get("ModuleName::#{class_model_name}")
or
Kernel.const_get("ModuleName::#{class_model_name}").
Upvotes: 0
Reputation: 405
Here is something that I came up with while looking for something similar that included module/namespace support:
['foo', 'bar'].inject {|r,e| "#{r.classify}::#{e.classify}"}.constantize
Produces
=> Foo::Bar
However this requires Rails and of course it only works where the array has more than one element.
This seems rather simple so I'm sure I'm missing something out, would anyone care to advise why this wouldn't be a good approach?
Thanks!
Upvotes: 2
Reputation: 101
None of the solutions I've seen work if you want to turn :foo_bar into FooBar. If that's what you're looking for:
:foo_bar.to_s.split("_").collect(&:capitalize).join.constantize
=> FooBar
hope that helps someone.
Upvotes: 10
Reputation: 54593
There are many ways to do this. Your lack of context makes it impossible to elect a "best" way. Here's a few ayways.
Kernel.const_get(:Bob)
eval(:Bob.to_s)
Kernel.const_get(:bob.to_s.capitalize)
Upvotes: 58
Reputation: 12396
class Bob
end
def create(name)
return eval("#{name}.new")
end
b = create(:Bob)
puts b.class
Upvotes: 2
Reputation: 370112
NameSpace.const_get(classname)
will return the class object (assuming that classname contains the name of a class - if it contains the name of a constant that is not a class, it will return the value of that constant). The toplevel namespace is Object, so you can do Object.const_get(:Bob).new
Upvotes: 5