Creating objects from strings

Hi,

I'm a Java programmer that is trying to learn Ruby.

I'm trying to write a container that creates objects on the fly from a descriptor. In Java I'd simply do Class.forName("MyClass").newInstance();

Is there an easy way to do this in Ruby? I basically want a loader that I can call Loader.createObject(filename, classname) where filename is the name of the ruby file containing the class and classname is the actual class.

Also, since I'll be creating more than one instance of each class, how do I store the class instance?

TIA.

Bill.

Bill wrote:

Hi,

I'm a Java programmer that is trying to learn Ruby.

I'm trying to write a container that creates objects on the fly from a descriptor. In Java I'd simply do Class.forName("MyClass").newInstance();

mc = Object.const_get( "MyClass" ).new

This presumes that the code already knows about the class MyClass (e.g., because the class is defined in the same file, or defined in a file that has already been read using 'require' or 'load').

BTW, I looked at the Ruby FAQ, and this question doesn't seem to be in there, despite its popularity.

http://dev.rubycentral.com/faq/

James

···

--

http://www.ruby-doc.org - The Ruby Documentation Site
http://www.rubyxml.com - News, Articles, and Listings for Ruby & XML
http://www.rubystuff.com - The Ruby Store for Ruby Stuff
http://www.jamesbritt.com - Playing with Better Toys

Hi,

I'm a Java programmer that is trying to learn Ruby.

I'm trying to write a container that creates objects on the fly from a
descriptor. In Java I'd simply do
Class.forName("MyClass").newInstance();

One way is like:
  Object.const_get("MyClass").new # returns an instance of MyClass
Or, if your classes are inside a module (say, "MyModule"), then
  MyModule.const_get("MyClass").new

Is there an easy way to do this in Ruby? I basically want a loader
that I can call Loader.createObject(filename, classname) where filename
is the name of the ruby file containing the class and classname is the
actual class.

Also, since I'll be creating more than one instance of each class, how
do I store the class instance?

  klass = Object.const_get("MyClass") # Returns the class MyClass
  obj = klass.new # Returns an instance of MyClass

There are probably other ways to do these things, but this is the one
I'm familiar with.

···

On 2005-06-05, Bill <ruby@thebackfamily.com> wrote:

Hi,

I'm a Java programmer that is trying to learn Ruby.

I'm trying to write a container that creates objects on the fly from a
descriptor. In Java I'd simply do
Class.forName("MyClass").newInstance();

Is there an easy way to do this in Ruby? I basically want a loader
that I can call Loader.createObject(filename, classname) where filename
is the name of the ruby file containing the class and classname is the
actual class.

Also, since I'll be creating more than one instance of each class, how
do I store the class instance?

You can always eval: obj = eval(classname).new, but this is cleaner:

cls = const_get classname
obj = cls.new

If you know the class is in some namespace (or other module):

cls = ModuleName.const_get classname

TIA.

Bill.

E

···

Le 5/6/2005, "Bill" <ruby@thebackfamily.com> a écrit:

--
template<typename duck>
void quack(duck& d) { d.quack(); }

Hi --

BTW, I looked at the Ruby FAQ, and this question doesn't seem to be in there, despite its popularity.

http://dev.rubycentral.com/faq/

That's an old address; the currently maintained FAQ is at:

   http://www.rubygarden.org/faq

I think Dave T. revised some links to point to that, but I guess the
old URL still goes to the older FAQ.

Not that the const_get question is answered on the current one either
:slight_smile: but I thought I'd mention the update.

David

···

On Sun, 5 Jun 2005, James Britt wrote:

--
David A. Black
dblack@wobblini.net

Thanks for all the quick help. The presumption was my problem. I had some code that I got that should have worked, but wasn't requiring the file. I'm now able to create classes from external files/modules with the following.

  def load (filename, classname)

    require filename

    # taken from http://www.ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-talk/9295
    names = classname.split /::confused:
    names.reverse!
    unf = Object
    unf = unf.const_get(names.pop) while names.length > 0
    unf.new
  end

load ("myfile.rb", "myModule::myClass")

···

On 2005-06-05 09:51:42 -0400, James Britt <james_b@neurogami.com> said:

Bill wrote:

Hi,

I'm a Java programmer that is trying to learn Ruby.

I'm trying to write a container that creates objects on the fly from a descriptor. In Java I'd simply do Class.forName("MyClass").newInstance();

mc = Object.const_get( "MyClass" ).new

This presumes that the code already knows about the class MyClass (e.g., because the class is defined in the same file, or defined in a file that has already been read using 'require' or 'load').

BTW, I looked at the Ruby FAQ, and this question doesn't seem to be in there, despite its popularity.

http://dev.rubycentral.com/faq/

James

David A. Black wrote:

Hi --

BTW, I looked at the Ruby FAQ, and this question doesn't seem to be in there, despite its popularity.

http://dev.rubycentral.com/faq/

That's an old address; the currently maintained FAQ is at:

  Captcha

I think Dave T. revised some links to point to that, but I guess the
old URL still goes to the older FAQ.

The FAQ I looked at is the first one that Google finds. Perhaps that page could be replaced with one that redirects to the current FAQ.

James

···

On Sun, 5 Jun 2005, James Britt wrote:

Bill wrote:

def load (filename, classname)

   require filename

   # taken from http://www.ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-talk/9295
   names = classname.split /::confused:
   names.reverse!
   unf = Object
   unf = unf.const_get(names.pop) while names.length > 0
   unf.new
end

load ("myfile.rb", "myModule::myClass")

This is an excellent place to use inject:

def load(filename, classname)
  require filename
  classname.split('::').inject(Object) {|module, name| module.const_get name}.new
end

You might also like to know that const_get will look in the parent modules as well. For example,

module A
  module B
  end
end

A.constants #=> ['B']
A.const_get :Object #=> Object

Because of this I've resorted to using eval "#{module}::#{name}" -- Does anyone know of a non-eval way of doing this?

And, as you may or may not know, Ruby comes with a load method, so you might want to change your method name to load_instance or something.

···

A::Object #=> Unitialized constant A::Object

this may be of interest

   http://www.codeforpeople.com/lib/ruby/dynaload/dynaload-0.0.0/README
   http://www.codeforpeople.com/lib/ruby/dynaload/

i use it for just this purpose.

cheers.

-a

···

On Mon, 6 Jun 2005, Bill wrote:

On 2005-06-05 09:51:42 -0400, James Britt <james_b@neurogami.com> said:

Bill wrote:

Hi,

I'm a Java programmer that is trying to learn Ruby.

I'm trying to write a container that creates objects on the fly from a descriptor. In Java I'd simply do Class.forName("MyClass").newInstance();

mc = Object.const_get( "MyClass" ).new

This presumes that the code already knows about the class MyClass (e.g., because the class is defined in the same file, or defined in a file that has already been read using 'require' or 'load').

BTW, I looked at the Ruby FAQ, and this question doesn't seem to be in there, despite its popularity.

http://dev.rubycentral.com/faq/

James

Thanks for all the quick help. The presumption was my problem. I had some code that I got that should have worked, but wasn't requiring the file. I'm now able to create classes from external files/modules with the following.

def load (filename, classname)

  require filename

  # taken from http://www.ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-talk/9295
  names = classname.split /::confused:
  names.reverse!
  unf = Object
  unf = unf.const_get(names.pop) while names.length > 0
  unf.new
end

load ("myfile.rb", "myModule::myClass")

--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
My religion is very simple. My religion is kindness.
--Tenzin Gyatso

===============================================================================