Skip to content

Instantly share code, notes, and snippets.

@myronmarston
Created February 18, 2013 03:32
Show Gist options
  • Save myronmarston/4974964 to your computer and use it in GitHub Desktop.
Save myronmarston/4974964 to your computer and use it in GitHub Desktop.
How does SimpleDelegator#method work?

How in the world does SimpleDelegator#method work?

  • SimpleDelegator subclasses BasicObject, which does not provide a method method.
  • Looking over the source, you can see that it doesn't define a method method anywhere.
  • It does define method_missing and proxy undefined methods to the delegated object...but I don't think that can be how it works, because both of these examples work:
class MyProxy < SimpleDelegator
  def undelegated
    :undelegated
  end 
end

p = MyProxy.new(:some_object)
p.method(:undelegated).call
SimpleDelegator.new(BasicObject.new).method(:object_id)

In the first example, it can't be proxying method to the :some_object because :some_object does not have an undelegated method. In the second example, it can't be proxying to the BasicObject because BasicObject lacks a method method, as already mentioned.

So how in the world does this work?

@phiggins
Copy link

@alindeman already pointed out that it comes from Kernel on twitter, but you can just ask #method where #method comes from:

 > class MyProxy < SimpleDelegator ; def undelegated ; :undelegated ; end ; end
 => nil 
 > MyProxy.method(:method)
 => #<Method: Class(Kernel)#method> 

@myronmarston
Copy link
Author

Thanks @phiggins, but MyProxy.method(:method) tells us about MyProxy.method, not MyProxy#method. MyProxy#method comes from an anonymous module:

1.9.3-p327 :032 > MyProxy.new(:foo).method(:method)
 => #<Method: MyProxy(#<Module:0x007ff619a991f8>)#method> 

This confirms that it comes from Kernel though...or rather, a dup of Kernel:

1.9.3-p327 :033 > ::Kernel.dup
 => #<Module:0x007ff619ae5788> 

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