intargc
intargc

Reputation: 3111

Ruby symbol to class

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

Answers (7)

Dan Frade
Dan Frade

Reputation: 1001

Rails

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

FredyK
FredyK

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

Joe
Joe

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

Lance Olsen
Lance Olsen

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

August Lilleaas
August Lilleaas

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

Tim Hoolihan
Tim Hoolihan

Reputation: 12396

class Bob
end

def create(name)
  return eval("#{name}.new")
end

b = create(:Bob)
puts b.class

Upvotes: 2

sepp2k
sepp2k

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

Related Questions