When Ruby tries to execute an undefined method (or, in object-oriented terms, when an object is sent a message that it cannot handle), the error causes the program to exit. You may prefer your program to recover from such an error. You can do this by writing a method named method_missing
, with an argument to which the missing method’s name is assigned. This will execute when a nonexistent method is called:
nomethod1.rb
def method_missing( methodname ) puts( "Sorry, #{methodname} does not exist" ) end xxx #=> Sorry, xxx does not exist
The method_missing
method can also take a list of incoming arguments (*args
) after the missing method name:
nomethod2.rb
def method_missing( methodname, *args ) puts( "Class #{self.class} does not understand: #{methodname}( #{args.inspect} )" ) end
Assuming the previous method_missing
method were written into a class called X, you could now attempt to call any method on an X object, whether or not that method exists and whether or not it is passed any arguments. If, for example, you were to attempt to call a nonexistent method called aaa
, first with no arguments and then with three integer arguments, the method_missing
method would respond to the invalid method call and display an appropriate error message:
ob = X.new ob.aaa #=> Class X does not understand: aaa( [] ) ob.aaa( 1,2,3 ) #=> Class X does not understand: aaa( [1, 2, 3] )
The method_missing
method could even create an undefined method dynamically so that a call to a nonexistent method automatically brings that method into existence:
def method_missing( methodname, *args ) self.class.send( :define_method, methodname, lambda{ |*args| puts( args.inspect) } ) end
Remember that the lambda
method turns a block (here the code between curly brackets) into a Proc object. This is explained in Chapter 10. The code is then able to pass this object as an argument to send
, defining a new method with the same name as the methodname
argument passed to method_missing
. The effect is that when an unknown method is called on a Z object, a method with that name is created. Run the nomethod2.rb program, which contains this code:
ob3 = Z.new ob3.ddd( 1,2,3) ob3.ddd( 4,5,6 )
This gives the following output:
Class Z does not understand: ddd( [1, 2, 3] ) Now creating method ddd( ) [4, 5, 6]
18.226.251.70