Converting a string to a class

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.

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"

···

On 2/22/06, Anthony DeRobertis <aderobertis@metrics.net> wrote:

Take the following snippet:

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.

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

···

On Feb 22, 2006, at 4:03 PM, Anthony DeRobertis wrote:

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...

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.

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

Gregory Brown 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...

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

···

On Feb 23, 2006, at 9:07 AM, Anthony DeRobertis wrote:

On 2/22/06, Anthony DeRobertis <aderobertis@metrics.net> wrote:

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

···

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

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

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

regards.

-a

···

On Fri, 24 Feb 2006, James Edward Gray II wrote:

On Feb 23, 2006, at 9:07 AM, Anthony DeRobertis wrote:

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...

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.

--
judge your success by what you had to give up in order to get it.
- h.h. the 14th dali lama

Thanks for the info. I'll have to keep that in mind.

Michael