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.
Anthony DeRobertis (Guest)
on 2006-02-23 00: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.
Gregory B. (Guest)
on 2006-02-23 00:23
(Received via mailing list)
On 2/22/06, Anthony DeRobertis <removed_email_address@domain.invalid> 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"
James G. (Guest)
on 2006-02-23 01: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 G. II
Anthony DeRobertis (Guest)
on 2006-02-23 17:11
(Received via mailing list)
Gregory B. wrote:

> On 2/22/06, Anthony DeRobertis <removed_email_address@domain.invalid> 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...
Anthony DeRobertis (Guest)
on 2006-02-23 17:11
(Received via mailing list)
James Edward G. 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.
Michael T. (Guest)
on 2006-02-23 17: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
James G. (Guest)
on 2006-02-23 17:44
(Received via mailing list)
On Feb 23, 2006, at 9:37 AM, Michael T. 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 G. II
James G. (Guest)
on 2006-02-23 17: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 G. II
unknown (Guest)
on 2006-02-23 18:15
(Received via mailing list)
On Fri, 24 Feb 2006, James Edward G. 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
Michael T. (Guest)
on 2006-02-23 18: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.