Forum: Ruby Dynamic object creation in ruby

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
5bf8afdc84e618eccb8531399bb69885?d=identicon&s=25 Clash Fasn (clashfan)
on 2009-03-29 05:30
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?
1bc63d01bd3fcccc36fb030a62039352?d=identicon&s=25 David Masover (Guest)
on 2009-03-29 06:49
(Received via mailing list)
Clash Fasn 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')
E16e84e861c1815ce11ba7bd851c857d?d=identicon&s=25 lasitha (Guest)
on 2009-03-29 06:54
(Received via mailing list)
On Sun, Mar 29, 2009 at 9:00 AM, Clash Fasn <bangclash@yahoo.com> 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
753dcb78b3a3651127665da4bed3c782?d=identicon&s=25 Brian Candler (candlerb)
on 2009-03-29 13:39
> frank = Object.const_get("Master::Person").new("Frank")
>
> Does anyone know why the second way fails?

frank = Master.const_get("Person").new("Frank")
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2009-03-29 15:55
(Received via mailing list)
On 29.03.2009 13:40, Brian Candler 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
9e2504e0b74e5384af09ce8a660afac4?d=identicon&s=25 Pascal J. Bourguignon (Guest)
on 2009-03-29 16:40
(Received via mailing list)
Robert Klemme <shortcutter@googlemail.com> writes:

> On 29.03.2009 13:40, Brian Candler 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.
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2009-03-29 17:55
(Received via mailing list)
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
This topic is locked and can not be replied to.