# Learning ruby - metaprogramming question

**URL:** <https://www.ruby-forum.com/t/learning-ruby-metaprogramming-question/73264>\
**Category:** Ruby\
**Created:** [October 23, 2006, 1:20pm UTC](https://www.ruby-forum.com/t/learning-ruby-metaprogramming-question/73264 "2006-10-23T13:20:25Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Luc\_J](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/8e7dd6/32.png) [@Luc\_J](https://www.ruby-forum.com/u/Luc_J)\
**Post date:** [October 23, 2006, 1:20pm UTC](https://www.ruby-forum.com/t/learning-ruby-metaprogramming-question/73264/1 "2006-10-23T13:20:25Z")

</div>

Hello all,

I started learning Ruby not long ago and I’d really like to understand  
concepts behind it.  
Poignant Guide to ruby ([http://poignantguide.net/ruby/chapter-6.html](http://poignantguide.net/ruby/chapter-6.html))  
is a very usefull book for this.  
Below example is extracted from this book and some things remain quite  
magical for me.

* * *

# The guts of life force within Dwemthy’s Array

class Creature

# Get a metaclass for this class

def self.metaclass; class \<\< self; self; end; end

# Advanced metaprogramming code for nice, clean traits

def self.traits( \*arr )  
return @traits if arr.empty?

```
 # 1. Set up accessors for each variable
 attr_accessor *arr

 # 2. Add a new class method to for each trait.
 arr.each do |a|
   metaclass.instance_eval do
     define_method( a ) do |val|
       @traits ||= {}
       @traits[a] = val
     end
   end
 end

 # 3. For each monster, the `initialize' method
 # should use the default number for each trait.
 class_eval do
   define_method( :initialize ) do
     self.class.traits.each do |k,v|
       instance_variable_set("@#{k}", v)
     end
   end
 end

```

end

* * *

## class Creature traits :life, :strength, :charisma, :weapon end

--------- generated Creature class ----------  
class Creature

# 1. set up reader and writer methods

attr\_accessor :life, :strength, :charisma, :weapon

# 2. add new class methods to use in creature

def self.life( val )  
@traits ||= {}  
@traits[‘life’] = val  
end

def self.strength( val )  
@traits ||= {}  
@traits[‘strength’] = val  
end

def self.charisma( val )  
@traits ||= {}  
@traits[‘charisma’] = val  
end

def self.weapon( val )  
@traits ||= {}  
@traits[‘weapon’] = val  
end

# 3. initialize sets the default points for

# each trait

def initialize  
self.class.traits.each do |k,v|  
instance\_variable\_set(“@#{k}”, v)  
end  
end

## end

The thing I do not really understand is the instance\_eval and  
class\_eval in the self.traits method.  
It seems that metaclass.instance\_eval define\_method create a Class  
method in the Creature class. Creating a method in the singleton class  
of a Class class always define a Class method? can the Singleton class  
can also be used to create an instance method of Creature ? Is the way  
presented in this example is what is commonly done to dynamically  
define Class and instance method of a Class or are there any other  
possible syntaxes ?

The self.traits method also define accessors methods: attr\_accessor  
\*arr, how come this is not done within a define\_method statement?

Well… I hope I am not getting to confusing…  
I would really appreciate your help as I’d really like to understand  
how that’s working.  
I have already read several article on metaprogramming but some things  
remain quite obscure to me 🙂

Thanks a lot,  
Luc

---

<div class="post-metadata">

**Author:** ![Luc\_J](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/8e7dd6/32.png) [@Luc\_J](https://www.ruby-forum.com/u/Luc_J)\
**Post date:** [October 23, 2006, 1:32pm UTC](https://www.ruby-forum.com/t/learning-ruby-metaprogramming-question/73264/2 "2006-10-23T13:32:39Z")

</div>

Hi –

On Mon, 23 Oct 2006, Luc J. wrote:

> The thing I do not really understand is the instance\_eval and  
> class\_eval in the self.traits method.  
> It seems that metaclass.instance\_eval define\_method create a Class  
> method in the Creature class. Creating a method in the singleton class  
> of a Class class always define a Class method?

Yes.

> can the Singleton class can also be used to create an instance  
> method of Creature ?

No, those methods will not be visible to instances of Creature. Think  
of it from the object’s perspective. Every object has a method  
look-up path, consisting of classes (including its singleton class)  
and modules. The whole point of a singleton class is that it lies on  
the look-up path of only one object. (There’s one exception to this;  
see below.) Therefore, if the class object Creature has a method in  
its singleton class, and you do: c = Creature.new, c is a different  
object from Creature, and the methods defined in Creature’s singleton  
class are not visible to it.

The exception is subclasses. If you subclass Creature, the new class  
will be able to call Creature’s singleton methods. It’s a special  
arrangement so that class methods can be inherited.

> Is the way presented in this example is what is commonly done to  
> dynamically define Class and instance method of a Class or are there  
> any other possible syntaxes ?

You can use eval(“def #{method\_name}…”) but it’s fragile and  
inadvisable.

> The self.traits method also define accessors methods: attr\_accessor  
> \*arr, how come this is not done within a define\_method statement?

The attr\_\* family of methods are basically wrappers around method  
definitions. They’re just shorter and more convenient, but the effect  
is the same.

David

---

<div class="post-metadata">

**Author:** ![Luc\_J](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/8e7dd6/32.png) [@Luc\_J](https://www.ruby-forum.com/u/Luc_J)\
**Post date:** [October 23, 2006, 1:36pm UTC](https://www.ruby-forum.com/t/learning-ruby-metaprogramming-question/73264/3 "2006-10-23T13:36:40Z")

</div>

Thanks a lot David,  
that clarified a lot of things in my head 🙂

Luc

---

<div class="post-metadata">

**Author:** ![Luc\_J](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/8e7dd6/32.png) [@Luc\_J](https://www.ruby-forum.com/u/Luc_J)\
**Post date:** [October 23, 2006, 5:05pm UTC](https://www.ruby-forum.com/t/learning-ruby-metaprogramming-question/73264/4 "2006-10-23T17:05:01Z")

</div>

Hi David,

Do you know where I could find some interesting doc on this, something  
like “Ruby Metaprogramming for “REAL” dummy” 🙂 ?

Thanks a lot,

Luc

---

<div class="post-metadata">

**Author:** ![Luc\_J](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/8e7dd6/32.png) [@Luc\_J](https://www.ruby-forum.com/u/Luc_J)\
**Post date:** [October 24, 2006, 5:17am UTC](https://www.ruby-forum.com/t/learning-ruby-metaprogramming-question/73264/5 "2006-10-24T05:17:20Z")

</div>

Luc J. wrote:

> Hi David,
> 
> Do you know where I could find some interesting doc on this, something  
> like “Ruby Metaprogramming for “REAL” dummy” 🙂 ?
> 
> Thanks a lot,
> 
> Luc

Hi Luc,

I have found Chapter 13, Ruby Dynamics, in Ruby for Rails by David A.  
Black, to be a great resource for getting your head around  
metaprogramming. I got started with Hal F.'s The Ruby Way, which I  
recommend as well (the 2nd edition comes out shortly, I think).

cheers,

Brian

---

<div class="post-metadata">

**Author:** ![Luc\_J](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/8e7dd6/32.png) [@Luc\_J](https://www.ruby-forum.com/u/Luc_J)\
**Post date:** [October 24, 2006, 1:16pm UTC](https://www.ruby-forum.com/t/learning-ruby-metaprogramming-question/73264/6 "2006-10-24T13:16:48Z")

</div>

Thanks a lot Brian,  
I’ll check this !!!

Luc
