views:

745

answers:

6

method_missing

*obj.method_missing( symbol h , *args i ) → other_obj*

Invoked by Ruby when obj is sent a message it cannot handle. symbol is the symbol for the method called, and args are any arguments that were passed to it. The example below creates a class Roman, which responds to methods with names consisting of roman numerals, returning the corresponding integer values. A more typical use of method_missing is to implement proxies, delegators, and forwarders.

class Roman
  def roman_to_int(str)
    # ...
  end
  def method_missing(method_id)
    str = method_id.id2name
    roman_to_int(str)
  end
end
r = Roman.new
r.iv ! 4
r.xxiii ! 23
r.mm ! 2000

I just heard about method-missing and went to find out more in Programming Ruby but the above explanation quoted from the book is over my head. Does anyone have an easier explanation? More specifically, is method-missing only used by the interpreter or is there ever a need to call it directly in a program (assuming I'm just writing web apps, as opposed to writing code for NASA)?

+5  A: 

It's basically a catch-all for messages that don't match up to any methods. It's used extensively in active record for dynamic finders. It's what lets you write something like this:

SomeModel.find_by_name_and_number(a_name, a_number)

The Model doesn't contain code for that find_by, so method_missing is called which looks at is says - I recognize that format, and carries it out. If it doesn't, then you get a method not found error.

Brian
+3  A: 

In the Roman example you provide it illustrates how you can extend the functionality of a class without explicitly defining methods.

r.iv is not a method so method_missing catches it and calls roman_to_int on the method id "iv"

It's also useful when you want to handle unrecognized methods elsewhere, like proxies, delegators, and forwarders, as the documentation states.

Leif
+10  A: 

It's probably best to not think of ruby as having methods. When you call a ruby "method" you are actually sending a message to that instance (or class) and if you have defined a handler for the message, it is used to process and return a value.

So method_missing is a special definition that gets called whenever ruby cannot find an apropriate handler. You could also think of it like a * method.

Samuel
"whenever ruby cannot find an apropriate handler" - don't i get an "undefined method" exception in that case? or is that exception coming from method_missing?
j. parks
Chatter, chatter, chatter (messages). How are we supposed to get any work done with all this small talk going on? :-)Good answer
Roboprog
Up voted for assumed Smalltalk reference.
Roman A. Taycher
+2  A: 

You do not call "method_missing" (the interpreter calls it). Rather, you define it (override it) for a class which you want to make to be more flexible. As mentioned in other comments, the interpreter will call your version of method_missing when the class (or instance) does not ("explicitly"?) define the requested method. This gives you a chance to make something up, based on the ersatz method/message name.

Have you ever done any "reflection" programming in Java? Using this method would be as if the class to be accessed via reflection could look at the string (excuse me, "symbol") of the method name if a no-such-method exception was thrown, and then make something up as that method's implementation on the fly.

Dynamic programming is kind of a "one-up" on reflection.

Roboprog
+4  A: 

Ruby doesn't have any type enforcement, and likewise doesn't do any checking as to what methods an object has when the script is first parsed, because this can be dynamically changed as the application runs.

What method_missing does, is let you intercept and handle calls to methods that don't exist for a given object. This provides the under-the-hood power behind pretty much every DSL (domain-specific language) written in Ruby.

In the case of the example, every one of 'r.iv', 'r.mm', and so on is actually a method call to the Roman object. Of course, it doesn't have an 'iv' or an 'mm' method, so instead control is passed to method_missing, which gets the name of the method that was called, as well as whatever arguments were passed.

method_missing then converts the method name from a symbol to a string, and parses it as a Roman number, returning the output as an integer.

Don Werve
-1: It doesn't check what methods it has at _parse-time_, but it most certainly does at run-time! Othersie how would it know that a method is missing?
Claudiu
@Claudiu: Fixed.
Don Werve
+1  A: 

Since you mention web apps I'll guess that you are familiar with Ruby on Rails. A good example of how method_missing can be used is the different find_by_<whatever> methods that's available. None of those methods actually exist! They are synthesized during run time. All of this magic happens because of how ruby intercepts invocations of non-existing methods.

You can read more about that and other uses of method_missing here.

sris