When I define a method inside instance_eval block for class it creates a class method which is fine.
Eg)
class A
end
A.instance_eval do
def method; end
end
A.method #works
But when I use define_method inside instance_eval it creates instance method instead of class method Eg)
A.instance_eval do
define_method(:method1) {}
end
A.method1 # NoMethodError: undefined method `method1'
A.new.method1 # Works fine
I am unable to understand above phenomena. Please can somebody help me out.
This quirky behavior makes a little more sense if you look at instance_eval
in the context of instances (which is its main purpose).
class A
end
a = A.new
a.instance_eval do
def foo
end
end
Where is foo
defined? The only sensible place I can think of is a
's singleton class, and indeed that is true
a.method(:foo).owner == a.singleton_class
# true
So this demonstrates the rule
def
insideinstance_eval
defines a method inself
's singleton class.
which is completely consistent with what you saw.
A.instance_eval do
# defines method in A's singleton class!
def method; end
end
So why does define_method
behave differently? Because unlike def
it's a method! So this
A.instance_eval do
define_method(:foo) {}
end
is really just
A.define_method(:foo) {}
which is the metaprogramming way of creating normal instance methods. This inconsistency may seem annoying, but again look at the case for normal instances and you'll see why def
and define_method
can't be consistent. This
a.instance_eval do
define_method(:foo) {}
end
is really just
a.define_method(:foo) {}
which is nonsense
NoMethodError: undefined method `define_method' for #<A:0x00008>