I would use Kernel#set_trace_func
method,to explain you what is going on under the hood. Look first the below code and the output:
trace = lambda do |event,file,line,id,binding,klass|
p [event,File.basename(file),line,id,binding,klass]
end
set_trace_func trace
class MyClass
def self.bar;end
def one
def two
end
end
end
obj = MyClass.new
obj.one
obj.instance_eval do
def three
end
end
output:
-----------------
----------------
-----------------
-----------------
-----------------
----------------- # part A
["c-call", "test.rb", 9, :singleton_method_added, #<Binding:0x83ab2b0>, BasicObject]
["c-return", "test.rb", 9, :singleton_method_added, #<Binding:0x83aaeb4>, BasicObject]
["line", "test.rb", 10, nil, #<Binding:0x83aab80>, nil]
["c-call", "test.rb", 10, :method_added, #<Binding:0x83aa900>, Module]
["c-return", "test.rb", 10, :method_added, #<Binding:0x83aa07c>, Module]
----------------------------- # part B
["line", "test.rb", 16, nil, #<Binding:0x83a976c>, nil]
["c-call", "test.rb", 16, :new, #<Binding:0x83a9488>, Class]
["c-call", "test.rb", 16, :initialize, #<Binding:0x83a90a0>, BasicObject]
["c-return", "test.rb", 16, :initialize, #<Binding:0x83a8e20>, BasicObject]
["c-return", "test.rb", 16, :new, #<Binding:0x83a8b28>, Class]
---------------------------
---------------------------
--------------------------- # part C
["c-call", "test.rb", 11, :method_added, #<Binding:0x83a7de0>, Module]
["c-return", "test.rb", 11, :method_added, #<Binding:0x83a79f8>, Module]
--------------------------- # part D
["line", "test.rb", 18, nil, #<Binding:0x83a7034>, nil]
["c-call", "test.rb", 18, :instance_eval, #<Binding:0x83a6c10>, BasicObject]
["line", "test.rb", 19, nil, #<Binding:0x83a65f8>, nil]
["c-call", "test.rb", 19, :singleton_method_added, #<Binding:0x83a61d4>, BasicObject]
["c-return", "test.rb", 19, :singleton_method_added, #<Binding:0x83a5ef0>, BasicObject]
["c-return", "test.rb", 18, :instance_eval, #<Binding:0x83a5d4c>, BasicObject]
Explanation:
Look at the 5 lines below part A. It simply tells us the when Ruby will find def
key word inside a class, it will add that method as an instance method to that class. This is being done by calling the hook method Module#method_added
. The same explanation goes to two lines below part C.
Now what goes on inside obj.instance_eval {..}
?
Ok,this will be cleared if you look at the lines below part D. Look from last, first and second line.Inside the instance_eval
block, def third
, causes third
to be added as a singleton_method
of the object ob
, by calling the hook method BasicObject#singleton_method_added
.
This is how MRI has been written.
def self.two; end
will behave like instance_eval – Snack