public Method

Kernel.method_missing(...)

obj.method_missing(symbol [, *args] )    result

Invoked by Ruby when obj is sent a message it cannot handle.

<i>symbol</i> is the symbol for the method called, and <i>args</i>
are any arguments that were passed to it. By default, the interpreter
raises an error when this method is called. However, it is possible
to override the method to provide more dynamic behavior.
The example below creates
a class <code>Roman</code>, which responds to methods with names
consisting of roman numerals, returning the corresponding integer
values.

   class Roman
     def romanToInt(str)

  end
  def method_missing(methId)
    str = methId.id2name
    romanToInt(str)
  end
end

r = Roman.new
r.iv      #=> 4
r.xxiii   #=> 23
r.mm      #=> 2000

Source Code

/*
*  call-seq:
*     obj.method_missing(symbol [, *args] )   => result
*  
*  Invoked by Ruby when <i>obj</i> is sent a message it cannot handle.
*  <i>symbol</i> is the symbol for the method called, and <i>args</i>
*  are any arguments that were passed to it. By default, the interpreter
*  raises an error when this method is called. However, it is possible
*  to override the method to provide more dynamic behavior.
*  The example below creates
*  a class <code>Roman</code>, which responds to methods with names
*  consisting of roman numerals, returning the corresponding integer
*  values.
*     
*     class Roman
*       def romanToInt(str)
*         # ...
*       end
*       def method_missing(methId)
*         str = methId.id2name
*         romanToInt(str)
*       end
*     end
*     
*     r = Roman.new
*     r.iv      #=> 4
*     r.xxiii   #=> 23
*     r.mm      #=> 2000
*/

static VALUE
rb_method_missing(argc, argv, obj)
   int argc;
   VALUE *argv;
   VALUE obj;
{
   ID id;
   VALUE exc = rb_eNoMethodError;
   char *format = 0;
   NODE *cnode = ruby_current_node;

   if (argc == 0 || !SYMBOL_P(argv[0])) {
       rb_raise(rb_eArgError, "no id given");
   }

   stack_check();

   id = SYM2ID(argv[0]);

   if (last_call_status & CSTAT_PRIV) {
       format = "private method `%s' called for %s";
   }
   else if (last_call_status & CSTAT_PROT) {
       format = "protected method `%s' called for %s";
   }
   else if (last_call_status & CSTAT_VCALL) {
       format = "undefined local variable or method `%s' for %s";
       exc = rb_eNameError;
   }
   else if (last_call_status & CSTAT_SUPER) {
       format = "super: no superclass method `%s'";
   }
   if (!format) {
       format = "undefined method `%s' for %s";
   }

   ruby_current_node = cnode;
   {
       int n = 0;
       VALUE args[3];

       args[n++] = rb_funcall(rb_const_get(exc, rb_intern("message")), '!',
                              3, rb_str_new2(format), obj, argv[0]);
       args[n++] = argv[0];
       if (exc == rb_eNoMethodError) {
           args[n++] = rb_ary_new4(argc-1, argv+1);
       }
       exc = rb_class_new_instance(n, args, exc);
       ruby_frame = ruby_frame->prev; /* pop frame for "method_missing" */
       rb_exc_raise(exc);
   }

   return Qnil;                /* not reached */
}
Comments

Have your say
Please use Textile formatting (click here for a cheat sheet). Use <code/> and <pre/> for code samples.
Click here to login with OpenID to to post comments.