---
title: Always Define respond_to_missing? When Overriding method_missing
teaser:
tags: web,ruby
author: Mike Burns
published_on: 2012-07-30
---

`method_missing` is still considered scary, but here's something more scary: forgetting to override `respond_to?`.

Whoa, right? Just gave you an anxiety attack there.

How about `#method`, though? Does that still work?

Go ahead, try it. Here, I'll try it with you:

    require 'ostruct'

    class Order
      def user
        @_user ||= OpenStruct.new(name: 'Mike', age: 28, occupation: 'slacker')
      end

      def method_missing(method_name, *arguments, &block)
        if method_name.to_s =~ /user_(.*)/
          user.send($1, *arguments, &block)
        else
          super
        end
      end

      def respond_to?(method_name, include_private = false)
        method_name.to_s.start_with?('user_') || super
      end
    end

OK now I'll load that into irb and play with it:

    ruby-1.9.2-p290> order = Order.new
     => #<Order:0x00000001e40948>
    ruby-1.9.2-p290> order.user_name
     => "Mike"
    ruby-1.9.2-p290> order.respond_to?(:user_name)
     => true
    ruby-1.9.2-p290> order.method(:user_name)
    NameError: undefined method `user_name' for class `Order'
      from (irb):23:in `method'
      from (irb):23
      from /home/mike/.rvm/rubies/ruby-1.9.2-p290/bin/irb:16:in `<main>'

[Denied!](http://www.youtube.com/watch?v=RD1KqbDdmuE)

There is a solution! How would you like to solve your `#method` problem while also using a method with a better name? For the low price of Ruby 1.9 you, too, can have this:

    require 'ostruct'

    class Order
      def user
        @_user ||= OpenStruct.new(name: 'Mike', age: 28, occupation: 'slacker')
      end

      def method_missing(method_name, *arguments, &block)
        if method_name.to_s =~ /user_(.*)/
          user.send($1, *arguments, &block)
        else
          super
        end
      end

      def respond_to_missing?(method_name, include_private = false)
        method_name.to_s.start_with?('user_') || super
      end
    end

But you don't have to take my word for it:

    ruby-1.9.2-p290> order = Order.new
    => #<Order:0x00000001c8d678>
    ruby-1.9.2-p290> order.user_name
    => "Mike"
    ruby-1.9.2-p290> order.respond_to?(:user_name)
    => true
    ruby-1.9.2-p290> order.method(:user_name)
    => #<Method: Order#user_name>

If I were to tweet about this, this is what I would say: **always define `respond_to_missing?` when overriding `method_missing`**.
