method_missing behaves differently when a method is called via reflection?

H

Hartin, Brian

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

class Foo
=20 def method_missing(method, *args, &block)
=20 "#{method} called"
=20 end
end

f =3D 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
=20 from (irb):8:in `initialize'
=20 from (irb):8
=20 =20
----

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 Hartin

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

Jacob Fugal

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?

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 Fugal
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,141
Latest member
BlissKeto
Top