Creating an instance from a variable

I have a class like this:

class Builder
    def Builder.create( klass, data )
        return klass.new(data)
    end
end

I want to call it as:

x = Builder.create( "Fred", data )

and get a object of type Fred.

I'm sure you can see what I am trying to do but for the life of me I can't get the syntax correct.

Hi Peter,

I have a class like this:

class Builder
    def Builder.create( klass, data )
        return klass.new(data)
    end
end

how about:

Class Builder
   def Builder.create( klass_sym, data )
      klass = Class.const_get( klass_sym )
      klass.new( data )
   end
end

x = Builder.create( :Fred, data )

Regards,

Matt

···

On Mon, 17 Jan 2005 19:54:47 +0900, Peter Hickman <peter@semantico.com> wrote:

--
Matt Mower :: http://matt.blogs.it/

return Kernel.const_get(klass).new(data)

Note that const_get will throw an exception if the passed class name is
unknown, so be prepared to deal with that.

···

Peter Hickman <peter@semantico.com> wrote:

        return klass.new(data)

--
Luc Heinrich - lucsky@mac.com

use (I have not tested this):

class Builder
    def Builder.create( klass, data )
        return Object.const_get(klass).new(data)
    end
end

*hth*,
Thomas

···

On Mon, 17 Jan 2005 19:54:47 +0900 Peter Hickman <peter@semantico.com> wrote:

I have a class like this:

class Builder
    def Builder.create( klass, data )
        return klass.new(data)
    end
end

--

\ Thomas Leitner -- thomas [underscore] leitner [at] gmx [dot] at

/ "Life is what happens to you while you're busy making other plans"

I'm not sure if this is what you want, but I think Kernel.const_get
can help you.
See changes below:

class Builder
    def Builder.create( klass, data )

         return Kernel.const_get(klass).new(data) #can pass in a string

    end
end

You might wanna do some error-catching too.

HTH!
CT

···

On Mon, 17 Jan 2005 19:54:47 +0900, Peter Hickman <peter@semantico.com> wrote:

Peter Hickman wrote:

I have a class like this:

class Builder
   def Builder.create( klass, data )
       return klass.new(data)
   end
end

I want to call it as:

x = Builder.create( "Fred", data )

Why don't just do x = Builder.create(Fred, data)?

Hi,

I have a class like this:

class Builder
   def Builder.create( klass, data )
       return klass.new(data)
   end
end

I want to call it as:

x = Builder.create( "Fred", data )

I just call

  class Fred
    def initialize data
      ...
    end
  end
  x = Builder.create Fred, data

or even

  r = Builder.create Regexp, '.*'

Bertram

···

Am Montag, 17. Jan 2005, 19:54:47 +0900 schrieb Peter Hickman:

--
Bertram Scharpf
Stuttgart, Deutschland/Germany
http://www.bertram-scharpf.de

Thanks for that it was just what I needed.

Thank you

Luc Heinrich wrote:

       return klass.new(data)
   
return Kernel.const_get(klass).new(data)

Note that const_get will throw an exception if the passed class name is
unknown, so be prepared to deal with that.

Actually, trying to catch the error seems to be harder than it should be. For example:

class Builder
   def Builder.create( klass_sym, data )
        begin
            return Kernel.const_get( klass_sym ).new( data )
        rescue
            raise "There was an error"
        end
   end
end

Should report "There was an error" when const_get fails. However this is untrapped.

xx.rb:26:in `const_get': uninitialized constant Bernie at Kernel (NameError)
        from xx.rb:26:in `create'
        from xx.rb:43

I've tried splitting this up into individual steps:

x = Kernel.const_get( klass_sym )
x.new( data )

but this makes no difference.

···

Peter Hickman <peter@semantico.com> wrote:

"Florian Gross" <flgr@ccan.de> schrieb im Newsbeitrag
news:351ujtF4fbbeiU1@individual.net...

Peter Hickman wrote:

> I have a class like this:
>
> class Builder
> def Builder.create( klass, data )
> return klass.new(data)
> end
> end
>
> I want to call it as:
>
> x = Builder.create( "Fred", data )

Why don't just do x = Builder.create(Fred, data)?

Why then not "Fred.new data"?
:slight_smile:

Regards

    robert

Hi

If you want to use strings, you could also do this (slight change)

class Builder
  def Builder.create(klass_name, data)
    Class.const_get(klass_name.intern).new(data)
  end
end

To note is the use of "intern" method which converts a string to a
symbol

HTH
Archit

···

On Mon, 2005-01-17 at 20:14 +0900, Matt Mower wrote:

Hi Peter,

On Mon, 17 Jan 2005 19:54:47 +0900, Peter Hickman <peter@semantico.com> wrote:
> I have a class like this:
>
> class Builder
> def Builder.create( klass, data )
> return klass.new(data)
> end
> end
>

how about:

Class Builder
   def Builder.create( klass_sym, data )
      klass = Class.const_get( klass_sym )
      klass.new( data )
   end
end

x = Builder.create( :Fred, data )

Regards,

Matt

Or try Ruby Facets:

  require 'facet/object/constant'

  class Builder
    def Builder.create( klass, *data )
      constant( klass ).new( *data )
    end
  end

T.

P.S. I debate with myself that the method might be better place in Kerenl, so
it might move there in future.

···

On Monday 17 January 2005 06:42 am, Peter Hickman wrote:

Luc Heinrich wrote:
>Peter Hickman <peter@semantico.com> wrote:
>> return klass.new(data)
>
>return Kernel.const_get(klass).new(data)
>
>Note that const_get will throw an exception if the passed class name is
>unknown, so be prepared to deal with that.

Actually, trying to catch the error seems to be harder than it should
be. For example:

class Builder
   def Builder.create( klass_sym, data )
        begin
            return Kernel.const_get( klass_sym ).new( data )
        rescue
            raise "There was an error"
        end
   end
end

Should report "There was an error" when const_get fails. However this is
untrapped.

xx.rb:26:in `const_get': uninitialized constant Bernie at Kernel
(NameError) from xx.rb:26:in `create'
        from xx.rb:43

I've tried splitting this up into individual steps:

x = Kernel.const_get( klass_sym )
x.new( data )

but this makes no difference.

"Peter Hickman" <peter@semantico.com> schrieb im Newsbeitrag
news:41EBA48B.1030901@semantico.com...

Luc Heinrich wrote:

>
>
>
>> return klass.new(data)
>>
>>
>
>return Kernel.const_get(klass).new(data)
>
>Note that const_get will throw an exception if the passed class name is
>unknown, so be prepared to deal with that.
>
>
>
Actually, trying to catch the error seems to be harder than it should
be. For example:

class Builder
   def Builder.create( klass_sym, data )
        begin
            return Kernel.const_get( klass_sym ).new( data )
        rescue
            raise "There was an error"
        end
   end
end

Should report "There was an error" when const_get fails. However this is
untrapped.

xx.rb:26:in `const_get': uninitialized constant Bernie at Kernel

(NameError)

        from xx.rb:26:in `create'
        from xx.rb:43

I've tried splitting this up into individual steps:

x = Kernel.const_get( klass_sym )
x.new( data )

but this makes no difference.

You need to catch NameError.

class Builder
   def Builder.create( klass_sym, data )
        begin
            return Kernel.const_get( klass_sym ).new( data )
        rescue NameError => e
            raise "There was an error: #{e}"
        end
   end
end

    robert

···

>Peter Hickman <peter@semantico.com> wrote:

Hi Robert,

"Florian Gross" <flgr@ccan.de> schrieb im Newsbeitrag
news:351ujtF4fbbeiU1@individual.net...
> Peter Hickman wrote:
>
> > I have a class like this:
> >
> > class Builder
> > def Builder.create( klass, data )
> > return klass.new(data)
> > end
> > end
> >
> > I want to call it as:
> >
> > x = Builder.create( "Fred", data )
>
> Why don't just do x = Builder.create(Fred, data)?

Why then not "Fred.new data"?
:slight_smile:

I'm porting my Make replacement Bake to Ruby and I do something
like

    class Real ; ...
    class Phony ; ...

    b = Builder.create target, name, prereqs, cmd

where `target' is either `Real' or `Phony'.

Bertram

···

Am Dienstag, 18. Jan 2005, 01:06:06 +0900 schrieb Robert Klemme:

--
Bertram Scharpf
Stuttgart, Deutschland/Germany
http://www.bertram-scharpf.de

Robert Klemme wrote:

You need to catch NameError.

class Builder
  def Builder.create( klass_sym, data )
       begin
           return Kernel.const_get( klass_sym ).new( data )
       rescue NameError => e
           raise "There was an error: #{e}"
       end
  end
end

   robert

Thanks for that, I thought that an open rescue would have caught it. Live and learn.

Thanks

"Bertram Scharpf" <lists@bertram-scharpf.de> schrieb im Newsbeitrag news:20050117170506.GB13393@homer.bertram-scharpf...

Hi Robert,

"Florian Gross" <flgr@ccan.de> schrieb im Newsbeitrag
news:351ujtF4fbbeiU1@individual.net...
> Peter Hickman wrote:
>
> > I have a class like this:
> >
> > class Builder
> > def Builder.create( klass, data )
> > return klass.new(data)
> > end
> > end
> >
> > I want to call it as:
> >
> > x = Builder.create( "Fred", data )
>
> Why don't just do x = Builder.create(Fred, data)?

Why then not "Fred.new data"?
:slight_smile:

I'm porting my Make replacement Bake to Ruby and I do something
like

   class Real ; ...
   class Phony ; ...

   b = Builder.create target, name, prereqs, cmd

where `target' is either `Real' or `Phony'.

??? Why can't you do

b = target.new name, prereqs, cmd

I mean, a class *is* a factory for its instances. If you don't have the requirement that the actual class of created instances might be different or want to keep that flexibility I don't see any added value in introducing a method for this.

Regards

    robert

···

Am Dienstag, 18. Jan 2005, 01:06:06 +0900 schrieb Robert Klemme:

Hi Robert,

"Bertram Scharpf" <lists@bertram-scharpf.de> schrieb im Newsbeitrag
>
>I'm porting my Make replacement Bake to Ruby and I do something
>like
>
> class Real ; ...
> class Phony ; ...
>
> b = Builder.create target, name, prereqs, cmd
>
>where `target' is either `Real' or `Phony'.

??? Why can't you do

b = target.new name, prereqs, cmd

I mean, a class *is* a factory for its instances. If you don't have the
requirement that the actual class of created instances might be different
or want to keep that flexibility I don't see any added value in introducing
a method for this.

Hm, seems to be a long time since I designed this. I
remember having thought very long and thoroughly about it.

I think I didn't tell the whole truth above. My code
actually looks like

  Rule.new Real, 'prog', 'prog.o', 'gcc ...'
  Rule.new Phony, 'all', 'prog'
  Suffix.new Real, '.o', '.c', 'gcc -c ...'

Multiple kinds of rules can instantiate multiple types of
targets. So, it is not possible to derive one from the
other.

Further, the suffix rule has to determine the target name
before it holds enough information to instantiate the target
itself.

(The whole program will be available soon.)

Bertram

···

Am Dienstag, 18. Jan 2005, 17:01:12 +0900 schrieb Robert Klemme:

--
Bertram Scharpf
Stuttgart, Deutschland/Germany
http://www.bertram-scharpf.de

"Bertram Scharpf" <lists@bertram-scharpf.de> schrieb im Newsbeitrag
news:20050118154256.GC7457@homer.bertram-scharpf...

Hi Robert,

> "Bertram Scharpf" <lists@bertram-scharpf.de> schrieb im Newsbeitrag
> >
> >I'm porting my Make replacement Bake to Ruby and I do something
> >like
> >
> > class Real ; ...
> > class Phony ; ...
> >
> > b = Builder.create target, name, prereqs, cmd
> >
> >where `target' is either `Real' or `Phony'.
>
> ??? Why can't you do
>
> b = target.new name, prereqs, cmd
>
> I mean, a class *is* a factory for its instances. If you don't have

the

> requirement that the actual class of created instances might be

different

> or want to keep that flexibility I don't see any added value in

introducing

> a method for this.

Hm, seems to be a long time since I designed this. I
remember having thought very long and thoroughly about it.

:slight_smile:

I think I didn't tell the whole truth above. My code
actually looks like

  Rule.new Real, 'prog', 'prog.o', 'gcc ...'
  Rule.new Phony, 'all', 'prog'
  Suffix.new Real, '.o', '.c', 'gcc -c ...'

Multiple kinds of rules can instantiate multiple types of
targets. So, it is not possible to derive one from the
other.

Further, the suffix rule has to determine the target name
before it holds enough information to instantiate the target
itself.

Ok, I see.

Kind regards

    robert

···

Am Dienstag, 18. Jan 2005, 17:01:12 +0900 schrieb Robert Klemme: