Dynamic object creation in ruby

I’m trying to do dynamic object creation in ruby.

This works:

john = eval(“Master::Person”).new(“John”)

This fails:

frank = Object.const_get(“Master::Person”).new(“Frank”)

Does anyone know why the second way fails?

Clash F. wrote:

This works:

john = eval(“Master::Person”).new(“John”)

This fails:

frank = Object.const_get(“Master::Person”).new(“Frank”)

Does anyone know why the second way fails?

Because there is no constant named Master::Person. There’s a constant
named Person inside the constant named Master. This is going to make a
lot more sense by example:

Object.const_get(‘Master’).const_get(‘Person’).new(‘Frank’)

For what it’s worth, unless there’s a reason to use strings, you may as
well use symbols there:

Object.const_get(:Master).const_get(:Person).new(‘Frank’)

On Sun, Mar 29, 2009 at 9:00 AM, Clash F. [email protected] wrote:

Does anyone know why the second way fails?

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

This will work:
Object.const_get(“Master”)::Person.new(“Frank”)

Or:
Object.const_get(“Master”).const_get(“Person”).new(“Frank”)

Or:
“Master::Person”.split(‘::’).reduce(Object){|cls, c| cls.const_get(c) }

But your question was ‘why?’… I guess the short answer is #const_get
just doesn’t interpret the scope operator, ‘::’. Actually, thinking
of it as an operator (hence it works in eval) and not a naming
convention is perhaps helpful.

cheers,
lasitha

frank = Object.const_get(“Master::Person”).new(“Frank”)

Does anyone know why the second way fails?

frank = Master.const_get(“Person”).new(“Frank”)

On 29.03.2009 13:40, Brian C. wrote:

frank = Object.const_get(“Master::Person”).new(“Frank”)

Does anyone know why the second way fails?

frank = Master.const_get(“Person”).new(“Frank”)

Erm, that’s a hybrid solution. If you know the names beforehand, you
can just do

frank = Master::Person.new “Frank”

I would assume that the OP receives the full qualified name as a String
and wants to get the class from there which can only be achieved with
any of the other solutions shown.

Cheers

robert

Robert K. [email protected] writes:

On 29.03.2009 13:40, Brian C. wrote:

frank = Object.const_get(“Master::Person”).new(“Frank”)

Does anyone know why the second way fails?
frank = Master.const_get(“Person”).new(“Frank”)

Erm, that’s a hybrid solution. If you know the names beforehand, you
can just do

frank = Master::Person.new “Frank”

Then the answer for the OP would be:

frank = Object.const_get(“Master”).const_get(“Person”).new(“Frank”)

const_get takes only a simple constant name, not a qualified name.

irb(main):247:0> (module Master
(class Person
(def initialize(name)
@name=name
end)
end)
end)
nil
irb(main):254:0> frank =
Object.const_get(“Master”).const_get(“Person”).new(“Frank”)
#<Master::Person:0x3465ac @name=“Frank”>

I would assume that the OP receives the full qualified name as a
String and wants to get the class from there which can only be
achieved with any of the other solutions shown.

Obviously, he wants to replace the literals by variables.

On 29.03.2009 16:38, Pascal J. Bourguignon wrote:

frank = Master::Person.new “Frank”

Then the answer for the OP would be:

frank = Object.const_get(“Master”).const_get(“Person”).new(“Frank”)

Why would anyone want to use Strings when he knows the names (and
consequently their number) beforehand? That does not make sense.

const_get takes only a simple constant name, not a qualified name.

Yes, and that’s why the solutions that were provided use some form of
String#split to cut a fully qualified name down to individual constants.

I would assume that the OP receives the full qualified name as a
String and wants to get the class from there which can only be
achieved with any of the other solutions shown.

Obviously, he wants to replace the literals by variables.

Apart from the plurals:

This works:

john = eval(“Master::Person”).new(“John”)

This fails:

frank = Object.const_get(“Master::Person”).new(“Frank”)

Regards

robert