In the below code snippet, I monkey patch Foo#bar with a define_method block. After I initialize a new instance of Foo, I overwrite it with a bind call to the parent class bar method, but when I call the method the block defined by the define_method block is called. Why doesn't the bind call change the behavior of the method?
class OriginalFoo
def bar
puts 'in OriginalFoo!'
end
end
class Foo < OriginalFoo
def bar
puts 'in Foo'
end
end
class Foo < OriginalFoo
old_bar = instance_method(:bar)
define_method(:bar) do
puts 'in define_method block'
old_bar.bind(self).call
end
end
foo_instance = Foo.new # => #<Foo:0x00007fe3ff037038>
OriginalFoo.instance_method(:bar).bind(foo_instance) # => #<Method: OriginalFoo#bar>
foo_instance.bar
# >> in define_method block
# >> in Foo
You're misunderstanding how UnboundMethod#bind works. You call Module#instance_method to get an UnboundMethod (i.e. a method without a self):
OriginalFoo.instance_method(:bar)
# #<UnboundMethod: ... >
Then you call UnboundMethod#bind to attach a self to that method, that returns a Method instance:
m = OriginalFoo.instance_method(:bar).bind(foo_instance)
# => #<Method: ...>
But that won't alter the method in foo_instance, all it does is make self your foo_instance when (or if) you said m.call: um.bind(obj) doesn't do anything to obj, it just gives you um as a Method that has obj as its self.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With