Instance from class name?

Hello,

I am new to this list (and language) but I didn't find my answer from the documentation available.

I simply would like to do something like:

myObject = class.fromName("a_class_name").new

I can do this in Java and Objective-C but didn't find how in Ruby. The idea is to have some configuration files for an activity which contain a class name to instantiate depending on the activity.

Many thanks (and sorry if this is an obvious question),

···

--
Alexander Lamb
Service d'Informatique Médicale
Hôpitaux Universitaires de Genève
Alexander.J.Lamb@sim.hcuge.ch
+41 22 372 88 62
+41 79 420 79 73

Hi --

···

On Thu, 13 Oct 2005, Alexander Lamb wrote:

Hello,

I am new to this list (and language) but I didn't find my answer from the documentation available.

I simply would like to do something like:

myObject = class.fromName("a_class_name").new

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

or some variation of that.

David

--
David A. Black
dblack@wobblini.net

David A. Black wrote:

Hi --

Hello,

I am new to this list (and language) but I didn't find my answer from the documentation available.

I simply would like to do something like:

myObject = class.fromName("a_class_name").new

Classes are stored as constants in ruby. Witness Mr. Black's solution:

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

or some variation of that.

That works; however, if your class name looks like SomeModule::SomeClass,
you will need to be a bit fancier because const_get only looks for constants
in the current class or module (the top-level Object instance is the default):

   class_name.split('::').inject(Object) {|parent, obj| parent.const_get obj}.new

#split creates an array ['SomeModule', 'SomeClass'], which we iterate over
using #inject. In the #inject block, the parent will always be the parent
class or module in which we look for the constant and obj is the next class
or module name. The Object is passed in as the initial parent object. the
parent.const_get obj sequence then looks like

   Object.const_get 'SomeModule' => => SomeModule.const_get 'SomeClass'

There may be a method to directly get the class in the future whether it is
nested or not. In the meanwhile, you can stick the above code in a method
if you will be using it a lot.

Also, you can always use #eval:

   obj = eval(class_name).new

Only, of course, if you trust the source of the class_name String. The
former method is preferred, though.

David

E

···

On Thu, 13 Oct 2005, Alexander Lamb wrote:

En réponse à ES :

That works; however, if your class name looks like SomeModule::SomeClass,
you will need to be a bit fancier because const_get only looks for constants
in the current class or module (the top-level Object instance is the default):

  class_name.split('::').inject(Object) {|parent, obj| parent.const_get obj}.new

Oh... my...!!! I thought I understood how inject works, but never would I have guessed that it was capable of such nifty things!!! This is... wow!

#split creates an array ['SomeModule', 'SomeClass'], which we iterate over
using #inject. In the #inject block, the parent will always be the parent
class or module in which we look for the constant and obj is the next class
or module name. The Object is passed in as the initial parent object. the
parent.const_get obj sequence then looks like

  Object.const_get 'SomeModule' => => SomeModule.const_get 'SomeClass'

When you explain it like that it makes perfect sense. But still... wow!!!

···

--
Christophe Grandsire (who's falling in love with Ruby again :slight_smile: ).

http://rainbow.conlang.free.fr

You need a straight mind to invent a twisted conlang.

Thanks for those pointers. The first suggestion worked and since I can trust the String of the name of the class, it is ok.

However, I didn't find it in the documentation of the Object class. I started on ruby-lang.org then was brought to rubycentral for the reference.
Is there another complete reference for ruby 1.8.x? (I am running on MacOSX 10.4.2).

Thanks,

···

--
Alexander Lamb
Service d'Informatique Médicale
Hôpitaux Universitaires de Genève
Alexander.J.Lamb@sim.hcuge.ch
+41 22 372 88 62
+41 79 420 79 73

On Oct 13, 2005, at 9:13 PM, ES wrote:

David A. Black wrote:

Hi --
On Thu, 13 Oct 2005, Alexander Lamb wrote:

Hello,

I am new to this list (and language) but I didn't find my answer from the documentation available.

I simply would like to do something like:

myObject = class.fromName("a_class_name").new

Classes are stored as constants in ruby. Witness Mr. Black's solution:

my_object = Object.const_get("MyClass").new
or some variation of that.

That works; however, if your class name looks like SomeModule::SomeClass,
you will need to be a bit fancier because const_get only looks for constants
in the current class or module (the top-level Object instance is the default):

  class_name.split('::').inject(Object) {|parent, obj| parent.const_get obj}.new

#split creates an array ['SomeModule', 'SomeClass'], which we iterate over
using #inject. In the #inject block, the parent will always be the parent
class or module in which we look for the constant and obj is the next class
or module name. The Object is passed in as the initial parent object. the
parent.const_get obj sequence then looks like

  Object.const_get 'SomeModule' => => SomeModule.const_get 'SomeClass'

There may be a method to directly get the class in the future whether it is
nested or not. In the meanwhile, you can stick the above code in a method
if you will be using it a lot.

Also, you can always use #eval:

  obj = eval(class_name).new

Only, of course, if you trust the source of the class_name String. The
former method is preferred, though.

David

E

Hi --

···

On Fri, 14 Oct 2005, ES wrote:

David A. Black wrote:

Hi --

On Thu, 13 Oct 2005, Alexander Lamb wrote:

Hello,

I am new to this list (and language) but I didn't find my answer from the documentation available.

I simply would like to do something like:

myObject = class.fromName("a_class_name").new

Classes are stored as constants in ruby. Witness Mr. Black's solution:

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

or some variation of that.

That works; however, if your class name looks like SomeModule::SomeClass,
you will need to be a bit fancier because const_get only looks for constants
in the current class or module (the top-level Object instance is the default):

class_name.split('::').inject(Object) {|parent, obj| parent.const_get obj}.new

Like Kernel#singleton_class, this is one of those things that gets
written again and again, ad hoc. I wonder if it might be a candidate
for a permanent modification to const_get....

David

--
David A. Black
dblack@wobblini.net

En réponse à Alexander Lamb :

However, I didn't find it in the documentation of the Object class. I started on ruby-lang.org then was brought to rubycentral for the reference.
Is there another complete reference for ruby 1.8.x? (I am running on MacOSX 10.4.2).

However, the best way is to use ri, the built-in documentation system for Ruby. Just type ri ClassOrModuleName#method to get the documentation for that instance method (without the #method, you get the documentation for the class or module itself, with lists of constants, class or module methods and instance methods, and for class or module methods the syntax is IIRC ri ClassOrModuleName::class_or_module_method).

But anyway, const_get isn't defined in Object but in Module. When you call Object.const_get, you are calling an instance method of the object "Object", which is an object of class "Class". Since Class inherits from Module, it inherits its instance method "const_get", which can thus be called on any object of class "Class", i.e. any class.

If you don't really understand it, do not fear. It took me a while to get it too. Just remember that in Ruby everything is an object, and that includes classes themselves :slight_smile: . So you can send methods to them too.

···

--
Christophe Grandsire.

http://rainbow.conlang.free.fr

You need a straight mind to invent a twisted conlang.

David A. Black wrote:

Hi --

David A. Black wrote:

Hi --

Hello,

I am new to this list (and language) but I didn't find my answer from the documentation available.

I simply would like to do something like:

myObject = class.fromName("a_class_name").new

Classes are stored as constants in ruby. Witness Mr. Black's solution:

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

or some variation of that.

That works; however, if your class name looks like SomeModule::SomeClass,
you will need to be a bit fancier because const_get only looks for constants
in the current class or module (the top-level Object instance is the default):

class_name.split('::').inject(Object) {|parent, obj| parent.const_get obj}.new

Like Kernel#singleton_class, this is one of those things that gets
written again and again, ad hoc. I wonder if it might be a candidate
for a permanent modification to const_get....

If only :slight_smile: Although I think that it might be more appropriate to have
something like ObjectSpace.const_get for that use.

David

E

···

On Fri, 14 Oct 2005, ES wrote:

On Thu, 13 Oct 2005, Alexander Lamb wrote:

Ah, I understand. Simply a class method (like in Objective-C). I just wasn't careful about the fact in inherited from Module (the class object hierarchy). This can be difficult to understand for Java developer who don't have real class objects and where static functions are not inherited.

Thanks,

···

--
Alexander Lamb
Service d'Informatique Médicale
Hôpitaux Universitaires de Genève
Alexander.J.Lamb@sim.hcuge.ch
+41 22 372 88 62
+41 79 420 79 73

On Oct 13, 2005, at 10:10 PM, Christophe Grandsire wrote:

En réponse à Alexander Lamb :

However, I didn't find it in the documentation of the Object class. I started on ruby-lang.org then was brought to rubycentral for the reference.
Is there another complete reference for ruby 1.8.x? (I am running on MacOSX 10.4.2).

http://www.ruby-doc.org/
However, the best way is to use ri, the built-in documentation system for Ruby. Just type ri ClassOrModuleName#method to get the documentation for that instance method (without the #method, you get the documentation for the class or module itself, with lists of constants, class or module methods and instance methods, and for class or module methods the syntax is IIRC ri ClassOrModuleName::class_or_module_method).

But anyway, const_get isn't defined in Object but in Module. When you call Object.const_get, you are calling an instance method of the object "Object", which is an object of class "Class". Since Class inherits from Module, it inherits its instance method "const_get", which can thus be called on any object of class "Class", i.e. any class.

If you don't really understand it, do not fear. It took me a while to get it too. Just remember that in Ruby everything is an object, and that includes classes themselves :slight_smile: . So you can send methods to them too.
--
Christophe Grandsire.

http://rainbow.conlang.free.fr

You need a straight mind to invent a twisted conlang.

Selon Alexander Lamb <Alexander.J.Lamb@sim.hcuge.ch>:

Ah, I understand. Simply a class method (like in Objective-C).

That's how it comes out yes :slight_smile: . I guess I could have said it just that way, but
then you'd still wonder why it was not in the documentation for Object :slight_smile: .

The thing to remember is that class methods are nothing more than instance
methods on the class object (when one defines class methods, one is just adding
singleton methods to the class object).

I just

wasn't careful about the fact in inherited from Module (the class
object hierarchy). This can be difficult to understand for Java
developer who don't have real class objects and where static
functions are not inherited.

The small diagram in the documentation of Class (you can see it by running ri
Class, or by looking in RDoc Documentation for the documentation of
class Class) is a good thing to keep in mind. It shows how the class Object is
an object of class Class, while at the same time Class inherits from Object via
Module :wink: . I must admit it took me a while to get it :wink: . And I still sometimes
get confused, which is why my explanation must have looked a bit confusing. I
was trying to rebuild my knowledge of the thing at the same time I wrote :slight_smile: .

···

--
Christophe Grandsire.

http://rainbow.conlang.free.fr

It takes a straight mind to create a twisted conlang.