How to create Class object with name determined at runtime

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

···

--
Posted via http://www.ruby-forum.com/.

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?

>> 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 Gray II

···

On Apr 28, 2006, at 12:36 PM, Bill Roberts 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

···

On Friday, April 28, 2006, at 02:55PM, Bill Roberts <bill.roberts@planet.nl> 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.

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

--
Posted via http://www.ruby-forum.com/\.

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

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

···

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.

James Gray wrote:

>> Object.const_get(cls)
=> Foo

Hope that helps.

James Edward Gray II

Yes it helps a lot! Thanks.

···

--
Posted via http://www.ruby-forum.com/\.

John Johnson 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.

···

--
Posted via http://www.ruby-forum.com/\.

} John Johnson 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

···

On Mon, May 01, 2006 at 08:52:12PM +0900, Bill Roberts wrote:

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 Fulton'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

···

--
Posted via http://www.ruby-forum.com/\.

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

···

On 5/1/06, Gregory Seidman <gsslist+ruby@anthropohedron.net> wrote:

Avoid using eval when possible.

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

···

On 5/3/06, Francisco Ortiz <ruby-talk@fjom.net> wrote:

On 5/1/06, Gregory Seidman <gsslist+ruby@anthropohedron.net> 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.