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 sayExtras.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 thenextend
the class that included us withExtras::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.