class methods in ruby modules

Modules in ruby are fairly simple to understand. You can add extra methods to a class by including a module.

  module Extras
    def say_hi
      puts "hello world"
    end
  end
  class Foo
    include Extras
  end
  Foo.new.say_hi

But one thing that crops up reasonably often (particularly in rails) is the need add not just methods, but class methods.

Now, the ever lovely textmate has a builtin snippet for doing just that. It appears to be a common ruby idiom.

  module Extras
    module ClassMethods
      def say_hi
        puts "hello world"
      end
    end

    extend ClassMethods

    def self.included(receiver)
      receiver.extend(ClassMethods)
    end
  end

The only thing I’ve added is the say_hi method. When included in class Foo, it lets us say Foo.say_hi

But what’s going on here? There are quite a few moving parts:

  • We define a second, nested module to hold the ClassMethods.
  • We extend Extras with ClassMethods. This is really Object.extend. So what’s the current object that this is being called on? Well, it turns out to be an instance of Module. This means that we’re pulling in all the methods in Extras::ClassMethods into Extras as well. But they’re defined as class methods, so you can say Extras.say_hi.
  • The next method, Module.included is a callback. It gets called whenever a this module is included by another class. It gets passed in a reference to that other class.
  • Inside included, we then extend the class that included us with Extras::ClassMethods. This makes all the class methods available in the class that included us.

This is all possible thanks to Ruby’s extremely open and consistent object model.