Mittwoch, 29. Mai 2013

Respond to method missing

You have to deal with dynamic method calls and somebody threw an "Implement method_missing" at you?
You google how to do it and maybe find an article like "method_missing, baby!". You code what you gotta code...
But that's only half of the truth. You probably missed to "respond_to?":
class Person
private
  def method_missing method_name, *args
    if %w(runs walks goes drives).include?(method_name.to_s)
      puts "#{self.class} #{method_name}."
    else
      super
    end
  end
end
which means, you broke the POLS (Principle Of Least Surprise):
person = Person.new
person.respond_to? :runs # => false
person.runs # => "Person runs."
Curious! An object, which claims not to respond to a receiver, but instead seem to respond? None would expect such behavior. The solution is to overwrite Person#respond_to? likewise:
class Person
  MOTIONS = %w(runs walks goes drives)
  def respond_to? method_name
    MOTIONS.include? method_name.to_s
  end

private
  def method_missing method_name, *args
    if MOTIONS.include?(method_name.to_s)
      puts "#{self.class} #{method_name}."
    else
      super
    end
  end
 end
and accordingly:
person = Person.new
person.respond_to? :runs # => true
person.runs # => "Person runs."
If it walks like a duck and if it quacks like duck, it is a duck. Ruby duck typing.
Lastly I want to point to another great article about the Principle Of Least Surprise: The Tao Of Programming. Funny.

Supported by Ruby 1.9.3

Kommentare:

  1. There was a discussion of this on Avdi Grimm's blog about a year ago. See:

    http://devblog.avdi.org/2011/12/07/defining-method_missing-and-respond_to-at-the-same-time/

    including some code from me to fix the problem, kinda-sorta. Maybe I should get back to packaging that up as a gem, as I intended....

    BTW, any chance of getting some internationalization on your blog buttons? I had to go over to Google Translate to figure out what Veroffentlichen and Vorschau mean.

    AntwortenLöschen
  2. Great blog post. Thank you.
    Do you work with Avdi Grimm?
    I love the Ruby Rogues podcasts (http://rubyrogues.com), which he is involved. They are awesome.

    AntwortenLöschen