Making Methods Available to Class and Instance in Ruby

Written by on Aug 6 2012

A few days ago I was contrasting extend and include in Ruby. In that post I said I would show you how to make a method available to both the class scope and the instance scope. You can do it by using the included  and extend methods:

module Log
  def Log.included cls
    cls.extend Log #also works by passing self, but Log is less confusing
  end
  def log str
    p str
  end  
end

class Thing
  include Log

  log "works from class"  # => "works from class"

  def test_log
    log "works from instance"
    self.log "works from self (in instance)"
    Thing.log "works from class (in instance)"
  end
end

Thing.new.test_log        # => "works from instance"
                          # => "works from self (in instance)"
                          # => "works from class (in instance)"

Module#included is called anytime the module is included in a class. When it is, we just call class.extend on the class that included the module and pass in self (which is the module).

Most people think just using the class method is fine, e.g. Rails.logger, but I like having a method available in both places. It makes me feel warm and fuzzy, like a blanket wrapped around me on a cold winter’s night…. Obviously you shouldn’t use this technique all the time, only when it makes sense.

Here is a nice general pattern for making modules:

module Mod
  module ClassMethods
    #put class methods here
  end

  module InstanceMethods
    #put instance methods here
  end

  def self.included(receiver)
    receiver.extend         ClassMethods
    receiver.send :include, InstanceMethods
  end
end
Meet
Steven

Hi I'm Steven,

I wrote the article you're reading... I lead the developers, write music, used to race motorcycles, and help clients find the right features to build on their product.

Get Blog Updates