Reading — step 1 of 7
Learn
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 freeEnumerable— implementeachand 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 module —
Geometry.newis 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 functions —def self.helperfor callable-on-the-module.def helperis 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…