How to create Class object with name determined at runtime


#1

I hope someone can help with this - I am a Ruby newbie.

In my code I want to decide at runtime which type of object to create,
based on a variable holding the name of the class.

So I have classes Foo and Bar and a string todays_class.

If todays_class = “Foo” I want to say my_obj = Foo.new
if todayS_class = “Bar” then my_obj = Bar.new

Except I’ve got a lot more than two classes and I’d prefer not to use an
if or case statement, so that I don’t need to change the code if I add
another one to the list.

Any suggestions on a neat way to do this?

Thanks


#2

On Apr 28, 2006, at 12:36 PM, Bill Roberts wrote:

Except I’ve got a lot more than two classes and I’d prefer not to
use an
if or case statement, so that I don’t need to change the code if I add
another one to the list.

Any suggestions on a neat way to do this?

class Foo; end
=> nil

class Bar; end
=> nil

cls = “Foo”
=> “Foo”

Object.const_get(cls)
=> Foo

Or, for nested classes…

?> class Foo

class Baz; end
end
=> nil

cls = “Foo::Baz”
=> “Foo::Baz”

cls.split("::").inject(Object) do |parent, constant|
?> parent.const_get(constant)

end
=> Foo::Baz

Hope that helps.

James Edward G. II


#3

James G. wrote:

Object.const_get(cls)
=> Foo

Hope that helps.

James Edward G. II

Yes it helps a lot! Thanks.


#4

John J. wrote:

You can use eval() to do that, like so:
irb(main):001:0> a=‘String’
=> “String”
irb(main):002:0> b=eval("#{a}.new")
=> “”
irb(main):003:0> b.class
=> String
irb(main):004:0>

In the second irb line, the contents of the variable a are substituted
in the string before the .new. It amounts to b=eval(“String.new”).

Regards,
JJ

John - thanks, also a neat solution. Having had experience mainly in
static/compiled languages previously, I am just getting to grips with
Ruby’s nice features for adapting itself as it runs.


#5

Having had experience mainly in

static/compiled languages previously, I am just getting to grips with
Ruby’s nice features for adapting itself as it runs.

you might want to check out Hal F.'s article ‘An Exercise in
Metaprogramming with Ruby’, where amongst other things he provides a
solution to your problem:

http://www.devsource.com/article2/0,1895,1928561,00.asp

_c


#6

You can use eval() to do that, like so:
irb(main):001:0> a=‘String’
=> “String”
irb(main):002:0> b=eval("#{a}.new")
=> “”
irb(main):003:0> b.class
=> String
irb(main):004:0>

In the second irb line, the contents of the variable a are substituted
in the string before the .new. It amounts to b=eval(“String.new”).

Regards,
JJ

On Friday, April 28, 2006, at 02:55PM, Bill Roberts
removed_email_address@domain.invalid wrote:

Except I’ve got a lot more than two classes and I’d prefer not to use an


Help everyone. If you can’t do that, then at least be nice.


#7

On Mon, May 01, 2006 at 08:52:12PM +0900, Bill Roberts wrote:
} John J. wrote:
} > You can use eval() to do that, like so:
} > irb(main):001:0> a=‘String’
} > => “String”
} > irb(main):002:0> b=eval("#{a}.new")
} > => “”
} > irb(main):003:0> b.class
} > => String
} > irb(main):004:0>
} >
} > In the second irb line, the contents of the variable a are
substituted
} > in the string before the .new. It amounts to b=eval(“String.new”).

Avoid using eval when possible.

irb(main):001:0> a=‘String’
=> “String”
irb(main):002:0> b=Object::const_get(a).new()
=> “”
irb(main):003:0> b.class
=> String
irb(main):004:0>

} > Regards,
} > JJ
} >
} >
} John - thanks, also a neat solution. Having had experience mainly in
} static/compiled languages previously, I am just getting to grips with
} Ruby’s nice features for adapting itself as it runs.
–Greg


#8

On 28 Apr 2006, at 18:36, Bill Roberts wrote:

I hope someone can help with this - I am a Ruby newbie.

In my code I want to decide at runtime which type of object to create,
based on a variable holding the name of the class.

It (may be) worth noting that because classes are “first class
objects” in Ruby, you can reference the actual class’s object with a
variable, if you wish:

class MyClass; end
c = MyClass
c.new

… sorry if I’m pointing out the very obvious.

Cheers,
Benj


#9

On 5/1/06, Gregory S. removed_email_address@domain.invalid wrote:

Avoid using eval when possible.

Hi Greg, would you mind telling me why? is this more expensive?
insecure?
I´m another newcomer to Ruby and this kind of tips are gold to me.

thanks!
Francisco


#10

On 5/3/06, Francisco O. removed_email_address@domain.invalid wrote:

On 5/1/06, Gregory S. removed_email_address@domain.invalid wrote:

Avoid using eval when possible.

Hi Greg, would you mind telling me why? is this more expensive? insecure?
I´m another newcomer to Ruby and this kind of tips are gold to me.

Mostly speed, but many people (myself included) find it easier to read.

const_get is about 10 times faster than eval:
ruby eval_bench.rb
user system total real
eval: 1.140000 0.000000 1.140000 ( 1.141000)
const_get: 0.157000 0.000000 0.157000 ( 0.156000)

#eval_bench.rb
require ‘benchmark’
class Foo;end
some_class = ‘Foo’
Benchmark.bm(10) do |b|
b.report(“eval:”) { 100000.times {eval("#{some_class}.new")} }
b.report(“const_get:”) {
100000.times{Object.const_get(some_class).new} }
end