Categories
Uncategorized

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.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s