How to include class and validation methods using a module in Ruby On Rails

Posted on 27 October 2009

A great way to re-use code across your Ruby on Rails application is to use a module and include the methods contained within it where you need them.

You simply create a file (typically named the same as your module) inside the lib directory where it is automatically loaded by Rails. For example a file lib/foo.rb may look like this...

module Foo

  def bar
    # ...
  end

end

Now in a class you can make the bar method available as an instance method thus:

include Foo

However, if you want to include a class method you need to modify the class that is including the module, this can be done using the included method. Most plugins use the included method as follows...

module Foo

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

  module ClassMethods
    def my_class_method
      # ...
    end
  end

  def bar
    # ...
  end

end

You simply put all your class methods inside the ClassMethods module (omitting the usual self part of the name).

However, this doesn't work for all class methods. For example validation methods and callbacks are typically called without the self prefix as it is implicit from the class that is defining the method. When including these methods you need to explicitly set the class, this can be achieved thus:

module Foo

  def self.included(base)
    base.validates_presence_of :bar
    base.before_save :some_method
  end

end

About Paul

Paul works for Kyan web design agency in Surrey, UK as a Ruby on Rails developer.

Follow Paul on Twitter

Email: paulsturgess [at] gmail.com

Read more articles in the archive →

Comments...

  • great site and very helpful. keep good work and thanks

    Dobril Bojilov at 02 Feb 10 at 21:09

  • Hallow, is nice but i d'ont know wath is this lang hhh
    i know only the php :)
    thank you any way

    THE-PHP-LOVER at 04 Feb 10 at 10:59

  • This is great, but I can't get it to work with attr_accessor. When I try to do base.attr_accessor, I get:
    private method `attr_accessor' called for Employee(id: integer, created_at: datetime, updated_at: datetime):Class

    Is there any way around this?

    Andrew Cone at 04 Oct 11 at 20:24

Got something to say?