# What's wrong with my metaprogramming?

**URL:** <https://www.ruby-forum.com/t/whats-wrong-with-my-metaprogramming/72135>\
**Category:** Ruby\
**Created:** [October 14, 2006, 5:15pm UTC](https://www.ruby-forum.com/t/whats-wrong-with-my-metaprogramming/72135 "2006-10-14T17:15:01Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![John\_Ky](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/c4cdca/32.png) [@John\_Ky](https://www.ruby-forum.com/u/John_Ky)\
**Post date:** [October 14, 2006, 5:15pm UTC](https://www.ruby-forum.com/t/whats-wrong-with-my-metaprogramming/72135/1 "2006-10-14T17:15:01Z")

</div>

> > > > >

def define\_my\_method(method\_name)  
define\_method method\_name do  
yield  
end  
end

class X  
define\_my\_method :method1 do  
puts “Method 1”  
end  
define\_my\_method :method2 do  
puts “Method 2”  
method1  
end  
end

X.new.method2  
\<\<\<\<\<

Gives:

C:\wrk\johnk\wiksprint-001\>define.rb  
Method 2  
C:/wrk/johnk/wiksprint-001/define.rb:13: undefined local variable or  
method `met hod1' for X:Class (NameError) from C:/wrk/johnk/wiksprint-001/define.rb:3:in`method2’  
from C:/wrk/johnk/wiksprint-001/define.rb:17

---

<div class="post-metadata">

**Author:** ![John\_Ky](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/c4cdca/32.png) [@John\_Ky](https://www.ruby-forum.com/u/John_Ky)\
**Post date:** [October 14, 2006, 5:23pm UTC](https://www.ruby-forum.com/t/whats-wrong-with-my-metaprogramming/72135/2 "2006-10-14T17:23:01Z")

</div>

Hi –

On Sun, 15 Oct 2006, John Ky wrote:

> end
> 
> C:\wrk\johnk\wiksprint-001\>define.rb  
> Method 2  
> C:/wrk/johnk/wiksprint-001/define.rb:13: undefined local variable or method  
> `met hod1' for X:Class (NameError) from C:/wrk/johnk/wiksprint-001/define.rb:3:in`method2’  
> from C:/wrk/johnk/wiksprint-001/define.rb:17

The problem is that define\_method creates instance methods – in this  
case, method1 and method2. In method2 you call method1… but you’re  
calling it on the class object X, when you’ve defined it for  
_instances_ of X.

If you replace method1 with new.method1, in the second call to  
define\_my\_method, you’ll see the difference.

David

---

<div class="post-metadata">

**Author:** ![John\_Ky](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/c4cdca/32.png) [@John\_Ky](https://www.ruby-forum.com/u/John_Ky)\
**Post date:** [October 14, 2006, 5:27pm UTC](https://www.ruby-forum.com/t/whats-wrong-with-my-metaprogramming/72135/3 "2006-10-14T17:27:02Z")

</div>

John Ky wrote:

try this one:

def define\_my\_method(method\_name,&blk)  
define\_method method\_name, &blk  
end

class X  
define\_my\_method :method1 do  
puts “Method 1”  
end  
define\_my\_method :method2 do  
puts “Method 2”  
method1  
end  
end

X.new.method2

lopex

---

<div class="post-metadata">

**Author:** ![John\_Ky](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/c4cdca/32.png) [@John\_Ky](https://www.ruby-forum.com/u/John_Ky)\
**Post date:** [October 14, 2006, 5:29pm UTC](https://www.ruby-forum.com/t/whats-wrong-with-my-metaprogramming/72135/4 "2006-10-14T17:29:02Z")

</div>

On Sun, 15 Oct 2006, John Ky wrote:

> end
> 
> C:\wrk\johnk\wiksprint-001\>define.rb  
> Method 2  
> C:/wrk/johnk/wiksprint-001/define.rb:13: undefined local variable or method  
> `met hod1' for X:Class (NameError) from C:/wrk/johnk/wiksprint-001/define.rb:3:in`method2’  
> from C:/wrk/johnk/wiksprint-001/define.rb:17

you don’t want yield here as the context of that yield is bound to the  
**class** (think of what self is at the time of call) and you want it  
bould to  
the instance.

harp:~ \> cat a.rb  
def define\_my\_method \*a, &b  
define\_method \*a, &b  
end

class X  
define\_my\_method :method1 do  
puts “Method 1”  
end  
define\_my\_method :method2 do  
puts “Method 2”  
method1  
end  
end

X.new.method2

harp:~ \> ruby a.rb  
Method 2  
Method 1

your metaprogramming is fine - this is an issue of blocks and scoping.

regards.

-a

---

<div class="post-metadata">

**Author:** ![John\_Ky](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/c4cdca/32.png) [@John\_Ky](https://www.ruby-forum.com/u/John_Ky)\
**Post date:** [October 14, 2006, 5:41pm UTC](https://www.ruby-forum.com/t/whats-wrong-with-my-metaprogramming/72135/5 "2006-10-14T17:41:47Z")

</div>

John Ky wrote:

> > > > > >
> 
> def define\_my\_method(method\_name)  
> define\_method method\_name do  
> yield  
> end  
> end

Yea, funny thing about Ruby, closures go a long ways. Have a look at  
what self is in one fo your definitions:

> class X  
> define\_my\_method :method1 do  
> puts “Method 1”  
> end  
> define\_my\_method :method2 do  
> puts “Method 2”  
> p self  
> method1  
> end  
> end
> 
> X.new.method2

This is why define\_method takes a block. So a fix would be:

def define\_my\_method(method\_name, &block)  
define\_method method\_name, &block  
end

Unfortuantely that’s not always the prefect solution since you might  
want to wrap extra code around the yield . In that case, you can use  
#instance\_eval if you don’t need to pass parameters. If you do need to  
pass parameters you’ll have to use more complicated tricks until 1.9  
introduces #instance\_exec.

On a related note, I still think it would be helpful if we could create  
clean-closure blocks.

T.
