When overriding #method_missing, remember to override #respond_to_missing? as well

Updated . Posted . Visible to the public.

When you use method_missing to have an object return something on a method call, always make sure you also redefine respond_to_missing?.

If you don't do it, nothing will break at a first glance, but you will run into trouble eventually.

Consider this class:

class Dog
  
  def method_missing(method_name, *args, &block)
    if method_name == :bark
      'woof!'
    else
      super
    end
  end
  
end

This will allow you to say:

Dog.new.bark
=> "woof!"

But:

Dog.new.respond_to? :bark
=> false

Lots of code (gems or your own) relies on respond_to? (for a good reason). For example #respond_to? Show archive.org snapshot will call #respond_to_missing? if the method is not defined within the receiver. When it has not been defined properly, its return value is a false negative!

Thus, you need to patch respond_to_missing? Show archive.org snapshot as well:

class Dog
  
  def method_missing(method_name, *args, &block)
    if method_name == :bark
      'woof!'
    else
      super
    end
  end
  
  def respond_to_missing?(method_name, *args)
    method_name == :bark or super
  end
  
end
 
Dog.new.bark
=> "woof!" 
Dog.new.respond_to? :bark
=> true 

Differences between respond_to? and respond_to_missing?

Note that old articles will recommend to override respond_to? instead of defining respond_to_missing?. You should always define respond_to_missing?, so your dynamic method will work with #method Show archive.org snapshot .

Example from Marc's post:

class StereoPlayer
  def method_missing(method, *args, &block)
    if method.to_s =~ /play_(\w+)/
      puts "Here's #{$1}"
    else
      super
    end
  end
  
  def respond_to?(method, *)
    method.to_s =~ /play_(\w+)/ || super
  end
end

StereoPlayer.new.respond_to? :play_beethoven # => true
StereoPlayer.new.method :play_beethoven
# => NameError: undefined method `play_some_Beethoven'
#               for class `StereoPlayer'
Profile picture of Arne Hartherz
Arne Hartherz
Last edit
Paul Demel
License
Source code in this card is licensed under the MIT License.
Posted by Arne Hartherz to makandra dev (2012-07-12 12:16)