Forum: Ruby Converting a string to a class

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.
2d0f17b478aa748b34afec2e5ec07b8d?d=identicon&s=25 Anthony DeRobertis (Guest)
on 2006-02-22 23:03
(Received via mailing list)
Take the following snippet:

module SomeModule
  class SomeClass
    SomeConstant = 3.1415
  end
end

   var = "SomeModule::SomeClass"
   print(var::SomeConstant)

This raises TypeError. So far, the only way I've found to do this (and
let me warn you, I'm quite new to Ruby so I may just be missing
something right in front of me) is like this:

  var = "SomeModule::SomeClass"
  eval "var = " + var
  print(var::SomeConstant)

which does indeed work, but I figure there has got to be a better way
than using eval.
31e038e4e9330f6c75ccfd1fca8010ee?d=identicon&s=25 Gregory Brown (Guest)
on 2006-02-22 23:23
(Received via mailing list)
On 2/22/06, Anthony DeRobertis <aderobertis@metrics.net> wrote:
> Take the following snippet:

why do string conversion?

You can pass constants around in ruby just fine.

D:\Documents and Settings\Administrator>irb
irb(main):001:0> a = String
=> String
irb(main):002:0> a.new
=> ""
irb(main):003:0>

also, to get at a constant within a class, you just do
SomeClass::SomeConstant

D:\Documents and Settings\Administrator>irb
irb(main):001:0> class A
irb(main):002:1> B = "hi"
irb(main):003:1> end
=> "hi"
irb(main):004:0> A::B
=> "hi"
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2006-02-23 00:21
(Received via mailing list)
On Feb 22, 2006, at 4:03 PM, Anthony DeRobertis wrote:

>
> This raises TypeError. So far, the only way I've found to do this (and
> let me warn you, I'm quite new to Ruby so I may just be missing
> something right in front of me) is like this:
>
>   var = "SomeModule::SomeClass"
>   eval "var = " + var
>   print(var::SomeConstant)
>
> which does indeed work, but I figure there has got to be a better way
> than using eval.

The usual idiom for this is const_get().  It's a little tricky in
this case, because of the nesting though:

 >> module SomeModule
 >>   class SomeClass
 >>     SomeConstant = 3.1415
 >>   end
 >> end
=> 3.1415
 >> var = "SomeModule::SomeClass"
=> "SomeModule::SomeClass"
 >> consts = var.split("::")
=> ["SomeModule", "SomeClass"]
 >> cls = consts.inject(Object) { |last, cur| last.const_get(cur) }
=> SomeModule::SomeClass
 >> puts cls::SomeConstant
3.1415
=> nil

Hope this gives you some fresh ideas.

James Edward Gray II
2d0f17b478aa748b34afec2e5ec07b8d?d=identicon&s=25 Anthony DeRobertis (Guest)
on 2006-02-23 16:11
(Received via mailing list)
Gregory Brown wrote:

> On 2/22/06, Anthony DeRobertis <aderobertis@metrics.net> wrote:
>> Take the following snippet:
>
> why do string conversion?
>
> You can pass constants around in ruby just fine.

I'm scanning a directory for plugins and loading them. When I load a
file called, for example, some_plugin.rb, I assume it creates a class
Whatever::Plugins::SomePlugin, which I naturally only have as a
string...
2d0f17b478aa748b34afec2e5ec07b8d?d=identicon&s=25 Anthony DeRobertis (Guest)
on 2006-02-23 16:11
(Received via mailing list)
James Edward Gray II wrote:

>  >> cls = consts.inject(Object) { |last, cur| last.const_get(cur) }
> => SomeModule::SomeClass

Thanks! That'll work great, especially since the SomeModule:: part is
constant, so I can just do SomeModule.const_get(name).

Thank you very much.
455ac2a64d06dc8461f4d258d7f7e980?d=identicon&s=25 Michael Trier (Guest)
on 2006-02-23 16:38
(Received via mailing list)
Just learning, but what's wrong with eval?  I do something like the
following in order to convert from a string to an object of the type
specified by the string:

a = "MyClass"
my_class = eval(a)
my_class.to_s

Michael
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2006-02-23 16:44
(Received via mailing list)
On Feb 23, 2006, at 9:37 AM, Michael Trier wrote:

> Just learning, but what's wrong with eval?  I do something like the
> following in order to convert from a string to an object of the type
> specified by the string:
>
> a = "MyClass"
> my_class = eval(a)
> my_class.to_s

eval() is a very powerful tool that we probably shouldn't use unless
we absolutely need too.  What if the String contains typos or
malicious code?  Also, it should be slower to compile and run some
code that to just do a constant lookup.  Probably better to use the
tools intended for the operation is all.

James Edward Gray II
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2006-02-23 16:59
(Received via mailing list)
On Feb 23, 2006, at 9:07 AM, Anthony DeRobertis wrote:

> file called, for example, some_plugin.rb, I assume it creates a class
> Whatever::Plugins::SomePlugin, which I naturally only have as a
> string...

You can do this without using the name assumptions in Ruby, if you
give them a class to inherit from.  Classes get notified when they
are subclassed:

 >> class Plugin
 >>   def self.inherited( plugin_class )
 >>     (@@plugins ||= Array.new) << plugin_class
 >>   end
 >>   def self.loaded
 >>     @@plugins || Array.new
 >>   end
 >> end
=> nil
 >> class FirstPlugin < Plugin; end
=> nil
 >> class SecondPlugin < Plugin; end
=> nil
 >> Plugin.loaded
=> [FirstPlugin, SecondPlugin]

Hope that gives you some fresh ideas.

James Edward Gray II
Cb48ca5059faf7409a5ab3745a964696?d=identicon&s=25 unknown (Guest)
on 2006-02-23 17:15
(Received via mailing list)
On Fri, 24 Feb 2006, James Edward Gray II wrote:

>>
>>>     (@@plugins ||= Array.new) << plugin_class
>>> Plugin.loaded
> => [FirstPlugin, SecondPlugin]
>
> Hope that gives you some fresh ideas.

i've abstracted this pattern as the 'dynaload' library here

   http://rubyforge.org/frs/?group_id=1024&release_id=3786

regards.

-a
455ac2a64d06dc8461f4d258d7f7e980?d=identicon&s=25 Michael Trier (Guest)
on 2006-02-23 17:15
(Received via mailing list)
Thanks for the info.  I'll have to keep that in mind.

Michael
This topic is locked and can not be replied to.