Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save chrisroos/3f9c7cb6cf284af149d98edb364c77dc to your computer and use it in GitHub Desktop.
Save chrisroos/3f9c7cb6cf284af149d98edb364c77dc to your computer and use it in GitHub Desktop.

I'm trying to synchronise the implementations of ClassMethod#restore_original_method and AnyInstanceMethod#restore_original_method in the hope that I can then remove the duplication.

In ClassMethod the @original_method is a Method (i.e. it's bound). In AnyInstanceMethod the @original_method is an UnboundMethod. I presume it's not possible to get hold of a bound method in AnyInstanceMethod as the class hasn't been instantiated at the point we get hold of it.

The define_method method accepts either a Method or UnboundMethod as the second argument. Although I can't use this form in Ruby 1.8.7 because of the "singleton method bound for a different object" problem (see https://gist.github.com/chrisroos/fc62b8e0ce30288abba6a3762b2cb1ee).

Given that I don't think I can get a bound Method in AnyInstanceMethod that means unbinding the method I have in ClassMethod.

I end up with the following code in ClassMethod#restore_original_method:

original_method = @original_method
receiver = stubbee
stubbee.__metaclass__.send(:define_method, method) do |*args, &block|
  original_method.bind(receiver).call(*args, &block)
end

And I end up with this code in AnyInstanceMethod#record_original_method:

original_method = @original_method
stubbee.send(:define_method, method) do |*args, &block|
  original_method.bind(self).call(*args, &block)
end

Unfortunately I can't currently see any way of making them the same!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment