Skip to content
Modules and Namespaces
step 1/7

Reading — step 1 of 7

Learn

~2 min readClasses, Inheritance, Modules

Modules are Ruby's other building block alongside classes. They serve TWO distinct roles: namespaces (organizing constants and classes) and mixins (sharing methods between unrelated classes).

Note: Ruby Intermediate covers mixins (include) in depth — this lesson is the introductory take.

Module as namespace

Group related code under a name to avoid global pollution:

module Geometry
  PI = 3.14159
  
  class Circle
    def initialize(radius)
      @radius = radius
    end
    def area
      Geometry::PI * @radius ** 2
    end
  end
  
  class Square
    def initialize(side)
      @side = side
    end
    def area
      @side ** 2
    end
  end
end

c = Geometry::Circle.new(5)
puts c.area
puts Geometry::PI

:: is the constant lookup operator. Geometry::Circle reads as "Circle inside Geometry."

Large Ruby projects (Rails, Sinatra, every gem) live inside top-level modules. Avoids name collisions when many gems are loaded together.

Module as mixin (preview — see Intermediate)

module Greetable
  def hello
    "Hello, I'm #{name}"
  end
end

class Person
  include Greetable        # mixes in Greetable's methods
  attr_accessor :name
end

p = Person.new
p.name = "Ada"
puts p.hello              # "Hello, I'm Ada"

include adds the module's methods as INSTANCE methods on the class. The class can use self/@name as if those methods were defined inside it.

A class can include any number of modules. Use cases:

  • Comparable — implement <=> and you get <, >, <=, >=, ==, between? for free
  • Enumerable — implement each and you get ~50 iteration methods (map, select, reduce, ...)

Module functions

Modules can hold standalone functions (like Python's modules):

module MathUtils
  def self.double(n)
    n * 2
  end
  
  def self.square(n)
    n ** 2
  end
end

puts MathUtils.double(5)       # 10
puts MathUtils.square(7)        # 49

def self.X inside a module declares a module function — callable as Module.X(...).

Nested namespaces

module MyApp
  module Models
    class User
      # ...
    end
  end
end

u = MyApp::Models::User.new

Deep nesting is common in larger codebases for organization. Rails uses this heavily — ActiveRecord::Base, ActionController::Base, etc.

extend — module-as-class-method-bag

include adds module methods as INSTANCE methods. extend adds them as CLASS methods:

module Counted
  def count
    @count ||= 0
  end
  def increment
    @count = count + 1
  end
end

class Tracker
  extend Counted          # class methods, not instance
end

Tracker.increment
Tracker.increment
puts Tracker.count        # 2

Different role from include: extend pulls the module's methods up to the class level.

Common mistakes

  • Confusing :: with .:: for constant lookup (modules, classes, constants), . for method calls. Top-level methods on modules can use either, but :: is conventional for constants.
  • Trying to instantiate a moduleGeometry.new is an error. Modules can't be instantiated.
  • Using a module when a class fits better — modules can't be instantiated and don't support inheritance. If you need instances, use a class.
  • Forgetting self. for module functionsdef self.helper for callable-on-the-module. def helper is for mixin use only.
  • Long namespace nesting — over-engineering. Two levels (AppName::Subarea) is usually enough.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…