Forum: Ruby Instantiate different class based on variable contents

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.
stephen O'D (Guest)
on 2009-04-09 00:40
(Received via mailing list)
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.
Tony A. (Guest)
on 2009-04-09 01:01
(Received via mailing list)
On Wed, Apr 8, 2009 at 2:40 PM, stephen O'D
<removed_email_address@domain.invalid>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(...)
Gary W. (Guest)
on 2009-04-09 01:14
(Received via mailing list)
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:
stephen O'D (Guest)
on 2009-04-09 02:01
(Received via mailing list)
On Apr 8, 10:01 pm, Tony A. <removed_email_address@domain.invalid> wrote:
>
> medioh.com
Thanks, works perfectly!
stephen O'D (Guest)
on 2009-04-09 02:05
(Received via mailing list)
On Apr 8, 10:13 pm, Gary W. <removed_email_address@domain.invalid> wrote:
> translate arbitrary text to a class name you are allowing arbitrary  
> >     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.
This topic is locked and can not be replied to.