2

method_missing shows up in Object.private_methods, not in Object.public_methods.

However, when I call Object.method_missing :stupidmethod, I get

NoMethodError: undefined method `stupidmethod' for Object:Class

I would expect to get

NoMethodError: private method `method_missing' called for Object:Class

because that's what I get when I try to invoke Object's other private methods, e.g. Object.chop.

As more evidence, if I call Object.method_missing without an argument, I get

ArgumentError: no id given

So it seems like I really am invoking that "private" method_missing function from outside of its object. Can you explain this?


EDIT: Thank you to Eugene in the comments. ruby --version tells me 1.8.7. Also, irb --version is 0.9.5(05/04/13). Good to know that this behaves as I'd expect in the later versions.

mziwisky
  • 335
  • 1
  • 12
  • maybe this [post](http://www.skorks.com/2010/04/ruby-access-control-are-private-and-protected-methods-only-a-guideline/) has the answer – tihom Sep 19 '13 at 18:39
  • 2
    With MRI 1.9.3 and 2.0.0 I actually do get a `NoMethodError`. Which Ruby implementation are you using? What is the context of your code? – Patrick Oscity Sep 19 '13 at 18:45
  • 3
    fwiw: I've verified that 1.9.3, 2.0, and rubinius all return a `private method method_missing` error. 1.8 and jruby (in 1.9 mode) return `undefined method stupidmethod` – Eugene Sep 19 '13 at 18:55

1 Answers1

1

It is not the private method of Object that is called but the module method in Kernel. You can check which method is called with set_trace_func as described in the answer to a similar question:

irb(main):001:1> set_trace_func proc { |event, file, line, id, binding, classname|   printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname if id.to_s == 'method_missing' }
=> #<Proc:0x0423d278@(irb):1>
irb(main):002:0> Object.method_missing :test
c-call (irb):4  method_missing   Kernel
c-return (irb):4  method_missing   Kernel
NoMethodError: undefined method `test' for Object:Class
    from (irb):4
    from :0

As some commenters pointed out in MRIs newer than 1.8.7 this behaviour has changed: method_missing has been removed from Kernel and the private instance method from Object was moved to BasicObject which is the new superclass.

Community
  • 1
  • 1
Arne
  • 422
  • 5
  • 16