define_method exhibits the following behaviour:
class TestClass
def exec_block(&block) ; yield ; end
end
TestClass.new.send(:exec_block) do ; puts self ; end
# -> main
TestClass.send(:define_method, :bing) do ; puts self ; end
TestClass.new.bing
# -> <TestClass:...>
What I do not understand is that the the block passed to define_method is supposed to be a closure. As such it should (at least according to my understanding) capture the value of self as main, as exhibited when calling exec_block.
I understand that the block will become the body of the method, yet I do not understand the reason for the behavior. Why does the block evaluate to different things when used with different methods ?
How can I reproduce the behavior of block with define_method for other methods ? i.e. how could I write exec_block to have it output <TestClass:...> instead of `main´ ?
selfis captured by the closure like any other variable. We can verify that by passing aProcaround different object instances:However,
BasicObject#instance_evaland the alikes rebind theselfvariable dynamically:Module#define_methodin turn usesinstance_evalto execute the associated block:Observe:
With that knowledge, you can now rewrite your
exec_blockto useinstance_eval:As mentioned before, using
instance_evalseems to be the only way to run aProcinstance with a modified context. It can be used to implement dynamic binding in Ruby.