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
def define_my_method(method_name)
define_method method_name do
yield
end
class X
define_my_method :method1 do
puts "Method 1"
end
define_my_method :method2 do
puts "Method 2"
method1
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
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.
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.
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
···
On Sun, 15 Oct 2006, John Ky wrote:
def define_my_method(method_name)
define_method method_name do
yield
end
class X
define_my_method :method1 do
puts "Method 1"
end
define_my_method :method2 do
puts "Method 2"
method1
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
--
my religion is very simple. my religion is kindness. -- the dalai lama
>>>>>
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.