# Exploring Metaprogramming

**URL:** <https://www.ruby-forum.com/t/exploring-metaprogramming/67453>\
**Category:** Ruby\
**Created:** [September 4, 2006, 2:44pm UTC](https://www.ruby-forum.com/t/exploring-metaprogramming/67453 "2006-09-04T14:44:05Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![mgreenly](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/85f322/32.png) [@mgreenly](https://www.ruby-forum.com/u/mgreenly)\
**Post date:** [September 4, 2006, 2:44pm UTC](https://www.ruby-forum.com/t/exploring-metaprogramming/67453/1 "2006-09-04T14:44:05Z")

</div>

I’ve got some downtime this weekend, so I’m pooring over various  
examples of  
metaprogramming w/ Ruby.

I really like \_why’s example regarding Dwemthy, but am curious as to how  
to  
achieve my end.

The article in question is here:

[http://poignantguide.net/ruby/chapter-6.html#section3](http://poignantguide.net/ruby/chapter-6.html#section3)

\_why’s method allows us to build ‘traits’ for the character (by calling  
the  
‘trait’ class method), and the meta programming behind the scenes builds  
an  
‘initialize’ instance method for the class.

What if I want to build a second method called ‘command’? It should  
place  
the argument in an array that can be referenced later. It will need to  
also  
build an initialize method for my class, but one of them will have to be  
overwritten.

Does anyone have any smart ways to combine or chain these two initialize  
methods together?

I ultimately want to do something like this:

class Dragon \< Creature  
traits :life  
life 100

command :fly

def fly  
puts “I am flying…”  
end

end

After an instance is created, it will contain the instance variable  
‘commands’, which is an array holding the symbol ‘fly’.

Does anyone have any ideas? In the end, I’d be adding more and more of  
these commands to my DSL. This is a DSL, right? 😉

---

<div class="post-metadata">

**Author:** ![mgreenly](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/85f322/32.png) [@mgreenly](https://www.ruby-forum.com/u/mgreenly)\
**Post date:** [September 4, 2006, 2:44pm UTC](https://www.ruby-forum.com/t/exploring-metaprogramming/67453/2 "2006-09-04T14:44:06Z")

</div>

On Sep 3, 2006, at 10:39 PM, Michael G. wrote:

> [http://poignantguide.net/ruby/chapter-6.html#section3](http://poignantguide.net/ruby/chapter-6.html#section3)  
> need to also  
> class Dragon \< Creature
> 
> After an instance is created, it will contain the instance variable  
> ‘commands’, which is an array holding the symbol ‘fly’.

here’s something to get you started:

class Creature  
def self.command(com)  
@commands ||= []  
@commands |= [com]  
end

def self.commands  
@commands ||= []  
end  
end

class Dragon \< Creature  
command :fly  
end

p Dragon.commands #=\> [:fly]

---

<div class="post-metadata">

**Author:** ![mgreenly](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/85f322/32.png) [@mgreenly](https://www.ruby-forum.com/u/mgreenly)\
**Post date:** [September 4, 2006, 2:44pm UTC](https://www.ruby-forum.com/t/exploring-metaprogramming/67453/3 "2006-09-04T14:44:06Z")

</div>

On Sep 3, 2006, at 10:39 PM, Michael G. wrote:

> initialize  
> def fly  
> these commands to my DSL. This is a DSL, right? 😉  
> Sorry I seem to have under estimated what you wanted.

try this instead:

% cat dragon.rb  
class Creature  
def self.command(cmd)  
old\_initialize = instance\_method(:initialize)  
define\_method(:initialize) do |\*args|  
@commands ||= []  
@commands |= [cmd]  
old\_initialize.bind(self).call(\*args)  
end  
end

def commands  
@commands ||= []  
end  
end

class Dragon \< Creature  
command :fly  
def fly  
puts “I’m flying”  
end

command :breathe\_fire

def breathe\_fire  
puts “I’m breathing fire!”  
end  
end

dragon = Dragon.new  
p dragon.commands

% ruby dragon.rb  
[:breathe\_fire, :fly]

---

<div class="post-metadata">

**Author:** ![mgreenly](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/85f322/32.png) [@mgreenly](https://www.ruby-forum.com/u/mgreenly)\
**Post date:** [September 4, 2006, 2:44pm UTC](https://www.ruby-forum.com/t/exploring-metaprogramming/67453/4 "2006-09-04T14:44:08Z")

</div>

Thanks a ton for this! This is amazing!

---

<div class="post-metadata">

**Author:** ![mgreenly](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/85f322/32.png) [@mgreenly](https://www.ruby-forum.com/u/mgreenly)\
**Post date:** [September 4, 2006, 2:44pm UTC](https://www.ruby-forum.com/t/exploring-metaprogramming/67453/5 "2006-09-04T14:44:12Z")

</div>

> -----Original Message-----  
> […]  
> On 9/3/06, Logan C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:  
> […]
> 
> > def commands  
> > @commands ||= []  
> > end  
> > end
> > 
> > class Dragon \< Creature  
> > command :fly  
> > def fly  
> > puts “I’m flying”  
> > end  
> > […]

I’m doing a very similar thing, but my approach was different. I have  
something vaguely like:

class Creature

```
class << self; attr_reader :commands end

def self.command( cmd )
	@commands ||= []
	@commands |= [cmd]
end
[...]
def initialize( *args )
	self.class.commands.each do |command| #do something
[...or maybe even...]
	@commands=self.class.commands

```

Which kind of puts a sticky note on the fridge of the derived class that  
it  
needs to do something, but allows you to put off what you’re doing until  
you’re actually instantiating the object. This way when you get to #do  
something, you can do it based on the arguments passed at initialize  
time,  
like say you get dragon=Dragon.new(AmazinglyPowerful) - you can make  
your  
breathe\_fire command hot enough to melt sand.

I have also actually been passing code as blocks:

Class Dragon \< Creature  
command :fly, proc {puts “Lookit me, Mom!”}  
end

Which lets you instance\_eval the block later in the correct namespace,  
or  
just define the method at runtime with define\_method. That can also be  
used  
in combination with a trick I found here on ruby-lang via google to  
instance\_eval a block with arguments; said trick will soon not be  
neccesary,  
so I’ll just add a note to google instance\_exec and you’ll probably dig  
it  
up fine.

Anyway, I really like the line above that rebinds the initialize method  
to  
perform a kind of ‘reverse super’…

old\_initialize.bind(self).call(\*args)

…and I’m trying to work out if it provides some benefits I have  
overlooked, apart from the fact that it will make the initialize method  
look  
a little cleaner and the things like self.command look a little messier.

Cheers,

ben
