Intantiating a class by name


#1

For the life of me I haven’t been able to find the syntax to
“instatiate” a class given it’s name. I know it’s silly. I feel silly
and when I hear the answer, I’ll fill twice as silly. Anyone wanna take
a stab at this and put me out of my misery?

erich


#2

Hi.

Say that you get a String like “A::b::C” and would like this
instantiated:

obj_class = Object
name.split( “::” ).each { |c| obj_class = obj_class.const_get( c ) } if
name
o = obj_class.new

Regards
Ola B.

----- Original Message -----
From: “Erich L. Timkar” removed_email_address@domain.invalid
Date: Wednesday, May 10, 2006 6:32 am
Subject: Intantiating a class by name
To: removed_email_address@domain.invalid (ruby-talk ML)


#3

class Foo

stuff

end

bar = Kernel.const_get(“Foo”).new

  • Jake McArthur

#4

No offense to the OP, but this is about the 5th time this has been
asked by Ruby Forum users in the last few weeks. Ruby Forum REALLY,
REALLY needs a FAQ with answers to questions like this.

FYI all Ruby Forum users: when you ask your questions they are sent
not just to Ruby Forum but to the ruby-talk mailing list, which has
probably thousands of subscribers.

Ryan


#5

I’m renaming and resending this post. I should have branched the
inappropriate subject when I first made my posting, sorry.

Sumary: Some questions come up regularly on the list. A wiki for answers
would be a superb resource. How about using:

http://www.rubygarden.org/ruby?QuestionsAndAnswers


#6

No offense to the OP, but this is about the 5th time this has been
asked by Ruby Forum users in the last few weeks. Ruby Forum REALLY,
REALLY needs a FAQ with answers to questions like this.

The Ruby Garden has a list of questions like this:

http://www.rubygarden.org/ruby?QuestionsAndAnswers

Specifically, this exact question is addressed:

http://www.rubygarden.org/ruby?FindClassesByName

[Brief discussion, and then two solutions for the the general case,
including an “inject” implementation.]

It’s been previously suggested that when questions like this are asked,
and good answers are given, they should be collected. This seems to be
an ideal location for such a catalogue. There are not too many answers
there yet (a dozen, or so). Perhaps in the future, more indexing would
be needed, but it looks ideal for now.

Cheers,
Benjohn


#7

Daniel S. wrote:

Isn’t it more appropriate to call #to_str on `name’? I.e.
name.to_str.split(…

Come to think of it, Symbol doesn’t define #to_str, so maybe this is
better:

name.to_sym.to_str.split(…

Furthermore, defining it in Module as a replacement for #const_get makes
sense, since they do the same thing, our version is just smarter:

class Module
alias_method :old_const_get, :const_get
def const_get(str)
names = str.to_sym.to_s.split(’::’)
names.inject(self){|parent, child| parent.old_const_get(child) }
end
end

class A; class B; class C; end; end; end

A.const_get :B => A::B
A::B.const_get :C => A::b::C
A.const_get “B::C” => A::b::C
Kernel.const_get “A::b::C” => A::b::C

Cheers,
Daniel


#8

Erich L. Timkar wrote:

For the life of me I haven’t been able to find the syntax to
“instatiate” a class given it’s name. I know it’s silly. I feel silly
and when I hear the answer, I’ll fill twice as silly. Anyone wanna take
a stab at this and put me out of my misery?

As the other guys have said, RubyGarden have the following
implementation:

def get_class(name)
name.split(/::/).inject{|parent, child| parent.const_get(child) }
end

I actually have two questions regarding this implementation:

  1. Is /::/' faster than“::”’?
  2. Isn’t it more appropriate to call #to_str on `name’? I.e.
    name.to_str.split(…

Cheers,
Daniel


#9

On May 10, 2006, at 6:32 AM, Erich L. Timkar wrote:

For the life of me I haven’t been able to find the syntax to
“instatiate” a class given it’s name. I know it’s silly. I feel
silly
and when I hear the answer, I’ll fill twice as silly. Anyone wanna
take
a stab at this and put me out of my misery?

class Foo; end

def make_new(klass)
klass.new
end

make_new(Foo) # => #Foo:0x2c4f4

Classes and modules are constants. If you have a string containing
the class/module name use the inject+const_get solution.

– Daniel


#10

On May 10, 2006, at 8:32 AM, Daniel S. wrote:

Come to think of it, Symbol doesn’t define #to_str, so maybe this
is better:

name.to_sym.to_str.split(…

You’re right it doesn’t, so how does explicitly converting name into
a symbol and then calling to_str help?

Ah nevermind I see from your code this was probably a typo. Then
riddle me this, why the double conversion?

to_sym.to_s should just be squished into to_s.


#11

I appreciate the array of options expressed on this. It really has
given a good perspective on my question. I guess I’ll do a more
extensive search on this issue, next time. Sorry to fill up your in
box.


#12

Logan C. wrote:

Ah nevermind I see from your code this was probably a typo.

Yup, it was supposed to read `to_sym.to_s’

Then riddle me this, why the double conversion?

to_sym.to_s should just be squished into to_s.

It may just be my own preference, but I think it’s nice to restrict the
`types’ of arguments a method can take – not by class, but by defined
methods. So when you say that #get_const takes a symbol as an argument,
you know you can give it every object that responds to #to_sym.

But yes, #to_s could be used.

Cheers,
Daniel