[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Instantiate different class based on variable contents

stephen O'D

4/8/2009 8:38:00 PM

Lets say I have a two classes, Foo and Bar.

In some code, I have a variable that can either contain the test 'Foo'
or the text 'Bar'. If it contains Foo, I would like to call Foo.new
(v1, v2), if it contains Bar, I would like to call Bar.new(v1, v2).

Obviously I could create an IF statement, such as

if var == 'Foo' then
Foo.new(...)
elsif var == 'Bar' then
Bar.new(...)
end if

Or if I want to get fancy, maybe a dispatch table:

dispatch = {
'Foo' => Foo,
'Bar' => Bar
}

obj = dispatch[var].new(...)

Is there another Ruby way to do this sort of thing?

Thanks,

Stephen.
4 Answers

Tony Arcieri

4/8/2009 9:01:00 PM

0

[Note: parts of this message were removed to make it a legal post.]

On Wed, Apr 8, 2009 at 2:40 PM, stephen O'D <stephen.odonnell@gmail.com>wrote:

> dispatch = {
> 'Foo' => Foo,
> 'Bar' => Bar
> }
>
> obj = dispatch[var].new(...)
>
> Is there another Ruby way to do this sort of thing?
>

Object.const_get(var).new(...)

or with ActiveSupport:

var.constantize.new(...)

--
Tony Arcieri
medioh.com

Gary Wright

4/8/2009 9:14:00 PM

0


On Apr 8, 2009, at 4:40 PM, stephen O'D wrote:
> dispatch = {
> 'Foo' => Foo,
> 'Bar' => Bar
> }
>
> obj = dispatch[var].new(...)


This can sometimes be the best approach because if you simply
translate arbitrary text to a class name you are allowing arbitrary
classes to be instantiated. It just depends on where your text is
coming from.

Rick DeNatale recently posted in [ruby-talk:332670] this nice solution
to mapping text to class objects:

> def constantize(camel_cased_word)
> camel_cased_word.
> sub(/^::/,'').
> split("::").
> inject(Object) { |scope, name| scope.const_defined?(name) ?
> scope.const_get(name) : scope.const_missing(name) }
> end


stephen O'D

4/8/2009 9:59:00 PM

0

On Apr 8, 10:01 pm, Tony Arcieri <t...@medioh.com> wrote:
> [Note:  parts of this message were removed to make it a legal post.]
>
> On Wed, Apr 8, 2009 at 2:40 PM, stephen O'D <stephen.odonn...@gmail.com>wrote:
>
> > dispatch = {
> >  'Foo' => Foo,
> >  'Bar' => Bar
> > }
>
> > obj = dispatch[var].new(...)
>
> > Is there another Ruby way to do this sort of thing?
>
> Object.const_get(var).new(...)
>
> or with ActiveSupport:
>
> var.constantize.new(...)
>
> --
> Tony Arcieri
> medioh.com

Thanks, works perfectly!

stephen O'D

4/8/2009 10:00:00 PM

0

On Apr 8, 10:13 pm, Gary Wright <gwtm...@mac.com> wrote:
> On Apr 8, 2009, at 4:40 PM, stephen O'D wrote:
>
> > dispatch = {
> >  'Foo' => Foo,
> >  'Bar' => Bar
> > }
>
> > obj = dispatch[var].new(...)
>
> This can sometimes be the best approach because if you simply  
> translate arbitrary text to a class name you are allowing arbitrary  
> classes to be instantiated.  It just depends on where your text is  
> coming from.
>
> Rick DeNatale recently posted in [ruby-talk:332670] this nice solution  
> to mapping text to class objects:
>
> > def constantize(camel_cased_word)
> >   camel_cased_word.
> >     sub(/^::/,'').
> >     split("::").
> >     inject(Object) { |scope, name| scope.const_defined?(name) ?
> > scope.const_get(name) : scope.const_missing(name) }
> > end
>
>

Thanks for the tip - I *think* my data is well enough sanitized, but
you just never know so I may well use this approach. Knowing how to
do things with Object.const_get is useful even if I don't use it.