Method_missing behaves differently when a method is called v

For certain methods, it seems to behave differently if called via
reflection. Consider the following example:

class Foo
def method_missing(method, *args, &block)
“#{method} called”
end
end

f = Foo.new

f.bar(‘a’)

-> “bar called”

f.send(:bar, ‘a’)

-> “bar called”

f.open(‘a’)

-> “open called”

f.send(:open, ‘a’)

Errno::ENOENT: No such file or directory - a
from (irb):8:in `initialize’
from (irb):8


I know that ‘open’ is a Kernel method, but I would have expected
f.open(‘a’) and f.send(:open, ‘a’) to behave similarly - either call the
Kernel method or call method_missing. Does anyone know why they’re
different?

Thanks,

Brian H.


This email may contain confidential material.
If you were not an intended recipient,
Please notify the sender and delete all copies.
We may monitor email to and from our network.


On 11/10/06, Hartin, Brian [email protected] wrote:

→ “open called”
f.open(‘a’) and f.send(:open, ‘a’) to behave similarly - either call the
Kernel method or call method_missing. Does anyone know why they’re
different?

All Kernel methods are private. Usually, a Kernel method is called in
procedural style (without a receiver) and since every object includes
Kernel, the private method is visible and called. But when there is an
explicit receiver (“receiver.method_name”), private methods are left
out of the lookup. So when you call f.open, the private Kernel#open is
masked and the unhandled method is passed on to method_missing.
Object#send, however, bypasses privacy restrictions so f.send(:open)
catches hold of Kernel#open and you get the error.

So, in short, it’s a matter of: private w/ send vs. private w/o send

Jacob F.