Modules and Mixins in Ruby
Modules provide namespaces and reusable behavior; mix them into classes.
Modules as namespaces
Group related constants and methods to avoid name collisions.
module MathUtil
PI = 3.14159
def self.circle_area(r)
PI * r * r
end
end
MathUtil::PI
MathUtil.circle_area(2)
Notes:
- Use modules to organize libraries and prevent constant collisions
- Access module methods via
Module.methodorModule::CONST
include, extend, prepend
include: adds module methods as instance methods (after the class in lookup)extend: adds module methods as class (singleton) methodsprepend: likeincludebut places the module before the class in the lookup chain
module Identified
def id
@id ||= SecureRandom.uuid
end
end
class User
include Identified # id becomes an instance method
end
u = User.new
u.id
class Registry
extend Identified # id becomes a class method here
end
Registry.id
Method lookup order
Use ancestors to see where Ruby searches methods.
User.ancestors
# => [User, Identified, Object, Kernel, BasicObject] (with include)
prepend puts the module before the class, allowing interception and super chaining.
module Logging
def save
puts "saving..."
super
end
end
class Repo
def save; :ok end
end
class Repo
prepend Logging
end
Repo.new.save # logs then calls original
module_function
Expose a method both as a module function and as a private instance method for mixin.
module Slug
def slugify(s)
s.downcase.gsub(/\W+/, '-')
end
module_function :slugify
end
Slug.slugify("Hello World") # callable on the module
Mix in standard behavior (Comparable)
Include Comparable and define <=> to get rich comparisons for free.
class Version
include Comparable
attr_reader :parts
def initialize(s) @parts = s.split('.').map!(&:to_i) end
def <=>(other) parts <=> other.parts end
end
Version.new("1.2") < Version.new("1.10") # => true
Hooks
React to mixins with callbacks.
module M
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
def enabled?; true end
end
end
class C; include M end
C.enabled?
Summary
- Use modules to namespace code and share behavior
- Choose
include/extend/prependbased on where methods should appear and intercept module_functiondual‑exposes utilities;Comparableunlocks comparisons with<=>