Reason #133 • May 13th, 2026

Extending classes with modules

Yesterday we looked at how Ruby's Module allows us to share behaviour between classes. In that example, we used include to mix in instance methods from the module. But what if we want to share class methods instead?

Ruby provides the extend method for this purpose:

Ruby
module Stockable
  def stock
    @stock ||= {}
  end

  def restock(item, quantity)
    stock[item] = quantity
  end

  def low_stock
    stock.select { |_, qty| qty < 5 }.keys
  end
end

class Tea
  extend Stockable
end

class Vinyl
  extend Stockable
end

Tea.restock("Earl Grey", 12)
Tea.restock("Chai Latte", 3)
Tea.low_stock # => ["Chai Latte"]

Vinyl.restock("Abbey Road", 8)
Vinyl.restock("Second Toughest in the Infants", 2)
Vinyl.low_stock # => ["Second Toughest in the Infants"]
    

Note: each class keeps its own @stock hash. The methods came from the same module, but the data lives on whichever class is calling them. So Tea's stock and Vinyl's stock never get tangled up.

Technically, extend adds the module to the class's singleton ancestor chain. That is to say, it is functionally equivalent to Tea.singleton_class.include(Stockable).

History

extend has been part of Ruby since its inception.

The machinery that makes extend work, the singleton class (aka "metaclass" or "eigenclass"), came from Smalltalk. While Smalltalk uses metaclasses only on classes, Ruby went a step further and exposed singleton classes for any object, and because classes are objects, they get the same treatment. Such is the beautiful consistency of Ruby's object model.

Reason #134 ?