Dynamic object creation in ruby

C

Clash Fasn

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?
 
D

David Masover

Clash said:
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')
 
L

lasitha

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?

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
 
R

Robert Klemme

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
 
P

Pascal J. Bourguignon

Robert Klemme said:
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.
 
R

Robert Klemme

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

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top