Skip to content

Instantly share code, notes, and snippets.

@jamesalmond
Last active December 28, 2015 07:29
Show Gist options
  • Save jamesalmond/7464398 to your computer and use it in GitHub Desktop.
Save jamesalmond/7464398 to your computer and use it in GitHub Desktop.
require 'delegate'
class Child
def open
"HELLO WORLD"
end
def ping
"PING"
end
end
class Parent < SimpleDelegator
end
parent = Parent.new(Child.new)
puts parent.ping
puts parent.send(:ping)
puts parent.open
puts parent.send(:open)
$ ruby delegate.rb
PING
PING
HELLO WORLD
delegate.rb:21:in `initialize': wrong number of arguments (0 for 1..3) (ArgumentError)
from delegate.rb:21:in `open'
from delegate.rb:21:in `<main>'
@carvil
Copy link

carvil commented Nov 14, 2013

It works if you use public_send instead of send. There is a private method called open somewhere in the inheritance chain that causes the error...

@hosiawak
Copy link

ping, send(:ping) and #open calls go via Delegator#method_missing but #send(:open) doesn't because Delegator includes a bunch of methods from Kernel

https://github.com/rubysl/rubysl-delegate/blob/2.0/lib/rubysl/delegate/delegate.rb#L44-L50

One of these methods is Kernel#open so send(:open) sees it in the inheritance chain for your parent and calls this directly instead of going via method_missing

You can "fix it":

require 'delegate'

class Delegator
  undef_method :open
end

and file a bug report to ruby-dev I guess.

@jamesalmond
Copy link
Author

Thanks @carvil and @hosiawak. It's an external library calling send so I can't change that without monkey patching.

@hosiawak, that's what's doing it! I worked out what was happening (i.e. calling Kernel#open) but couldn't work out why

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