Question
I am learning Ruby metaprogramming and trying to understand how modules and mixins work.
From what I understand:
includeadds a module's methods as instance methods to a classextendadds a module's methods as class methods to a class
Is that the main difference, or is there more to it?
For example:
module ReusableModule
def module_method
puts "Module Method: Hi there!"
end
end
class ClassThatIncludes
include ReusableModule
end
class ClassThatExtends
extend ReusableModule
end
puts "Include"
ClassThatIncludes.new.module_method
puts "Extend"
ClassThatExtends.module_method
Why does include make the method available on instances, while extend makes it available on the class itself?
Short Answer
By the end of this page, you will understand what include and extend do in Ruby, how they affect method lookup, why one adds instance methods and the other adds class-level behavior, and when to use each in real code.
Concept
Ruby modules are a way to group reusable behavior.
When you add a module to a class, the key question is: who should receive those methods?
- With
include, the module is inserted into the class's ancestor chain so its methods become available to instances of that class. - With
extend, the module is added to a specific object's singleton class, so its methods become available to that object itself.
That is why this works differently for classes:
- A class in Ruby is also an object
- So when you
extend SomeModuleinside a class, you are adding methods to the class object, which appear as class methods
Why this matters
This distinction shows up everywhere in Ruby:
- sharing behavior between instances of many classes
- adding utility methods to a class
- building DSLs
- Rails concerns and macros
- metaprogramming patterns
The short version is:
include= instances gain the module's methodsextend= the receiver itself gains the module's methods
So yes, your summary is mostly correct. The deeper idea is that extend is not specifically about class methods. It adds methods to any object you call it on. If that object happens to be a class, they look like class methods.
Mental Model
Think of a module as a toolkit.
includeputs the toolkit into every worker created from a classextendputs the toolkit directly into the factory itself
If CarFactory includes a module, then each car built by the factory can use those tools.
If CarFactory extends a module, then the factory can use those tools directly.
Another way to see it:
includeaffects future instancesextendaffects the current object
Since classes are objects in Ruby, extending a class means the class object gets those methods.
Syntax and Examples
Core syntax
module MyModule
def greet
"Hello"
end
end
class Person
include MyModule
end
class Robot
extend MyModule
end
Example: include
module Speakable
def speak
"I can speak"
end
end
class Human
include Speakable
end
person = Human.new
puts person.speak
# => I can speak
What happened?
Speakabledefines an instance method:speakHumanincludes the module- Every
Humanobject can now callspeak
Example: extend
module Identifiable
def category
"Machine"
end
end
class Robot
extend Identifiable
end
puts Robot.category
# => Machine
What happened?
Robotis an object of classClassextend Identifiableaddscategoryto theRobotobject itself- So
Robot.categoryworks - But
Robot.new.categorywould fail unless the module was also included
Same module, both behaviors
module Demo
def hello
"hello"
end
end
class Example
include Demo
extend Demo
end
puts Example.hello
# => hello
puts Example.new.hello
# => hello
This class can use hello both as a class method and an instance method.
Step by Step Execution
Consider this code:
module ReusableModule
def module_method
"Module Method: Hi there!"
end
end
class ClassThatIncludes
include ReusableModule
end
class ClassThatExtends
extend ReusableModule
end
Step-by-step
1. Ruby defines the module
module ReusableModule
Ruby creates a module object named ReusableModule.
2. The method is stored in the module
def module_method
"Module Method: Hi there!"
end
This becomes an instance method of the module, ready to be mixed into something else.
3. ClassThatIncludes includes the module
class ClassThatIncludes
include ReusableModule
end
Ruby inserts ReusableModule into the ancestor chain of ClassThatIncludes.
So when you call:
ClassThatIncludes.new.module_method
Ruby looks for module_method in this order:
- the instance
ClassThatIncludesReusableModule- superclass chain
It finds the method in ReusableModule, so the instance can use it.
4. ClassThatExtends extends the module
class ClassThatExtends
extend ReusableModule
end
Here, the receiver is the class object ClassThatExtends.
Ruby adds the module to that object's singleton class.
So when you call:
ClassThatExtends.module_method
Ruby looks for methods on the ClassThatExtends object itself and finds module_method there.
5. Important result
ClassThatIncludes.module_method
# => NoMethodError
ClassThatExtends.new.module_method
# => NoMethodError
Each keyword affects a different receiver.
Inspecting ancestors
You can see part of this behavior directly:
module ReusableModule
def module_method
end
end
class ClassThatIncludes
include ReusableModule
end
p ClassThatIncludes.ancestors
# => [ClassThatIncludes, ReusableModule, Object, Kernel, BasicObject]
This shows that ReusableModule is in the method lookup chain for instances of ClassThatIncludes.
Real World Use Cases
When to use include
Use include when every instance of a class should share common behavior.
Examples:
- formatting methods for model objects
- permission-checking behavior for service objects
- reusable validation helpers
- logging behavior for instances
- comparable behavior like
Enumerable
module Printable
def print_name
puts name
end
end
class User
include Printable
attr_reader :name
def initialize(name)
@name = name
end
end
When to use extend
Use extend when you want to add behavior to one specific object, often a class.
Examples:
- class-level helper methods
- configuration APIs
- DSL-style macros
- utility behavior on a single object
module FindByName
def find_by_name(name)
puts "Finding #{name}"
end
end
class User
extend FindByName
end
User.find_by_name("Alice")
Extending a regular object
extend is not limited to classes.
module Debuggable
def debug
"debug info"
end
end
item = "hello"
item.extend(Debuggable)
puts item.debug
# => debug info
Only that one string object gets the method.
Real Codebase Usage
In real Ruby projects, include and extend are often used in patterns rather than isolation.
1. Shared instance behavior with include
A common use is to keep classes small by moving reusable instance methods into modules.
module TimestampFormatter
def formatted_time(time)
time.strftime("%Y-%m-%d")
end
end
class Report
include TimestampFormatter
end
2. Class-level APIs with extend
Libraries often use extend to add class methods that act like macros.
module Configurable
def setting(name, value)
@settings ||= {}
@settings[name] = value
end
def settings
@settings || {}
end
end
class AppConfig
extend Configurable
setting :timeout, 30
end
3. Using both together
A frequent pattern is:
includefor instance methodsextendfor class methods
module Trackable
def track
"instance tracking"
end
module ClassMethods
def tracking_enabled?
true
end
end
def self.included(base)
base.extend(ClassMethods)
end
end
class Order
include Trackable
end
puts Order.tracking_enabled?
puts Order.new.track
This pattern appears in many Ruby libraries and frameworks.
4. Guard clauses and validation helpers
Modules included into classes often centralize common checks.
module Validatable
def validate_name!(name)
raise ArgumentError, "name required" if name.to_s.strip.empty?
end
end
5. DSL building
Ruby frameworks often extend classes with methods like:
has_manybefore_actionvalidates
These are usually class-level methods added with extend directly or indirectly.
Common Mistakes
1. Thinking extend only works for classes
It works on any object.
module Extra
def hello
"hello"
end
end
obj = Object.new
obj.extend(Extra)
puts obj.hello
2. Expecting include to create class methods
Broken example:
module Helper
def do_work
"done"
end
end
class Task
include Helper
end
Task.do_work
# NoMethodError
Fix
Call the method on an instance:
Task.new.do_work
Or use extend if you want a class method:
class Task
extend Helper
end
3. Expecting instances to get methods from extend
Broken example:
module Helper
def do_work
"done"
end
end
class Task
extend Helper
end
Task.new.do_work
# NoMethodError
Fix
Use include for instance methods.
4. Mixing up module methods and mixed-in methods
This is a different thing:
module Tool
def self.info
"module-level method"
end
end
Tool.info
def self.info creates a method on the module object itself. That method is not what include mixes into classes.
To mix in methods, define them like this instead:
module Tool
def info
"instance-style method for mixing in"
end
end
5. Forgetting method lookup order
If a class and a module define the same method, the class method wins.
module Greeting
def hello
"from module"
end
end
class Person
include Greeting
def hello
"from class"
end
end
puts Person.new.hello
# => from class
Know that mixins participate in Ruby's ancestor chain.
Comparisons
| Feature | include | extend |
|---|---|---|
| Adds methods to | Instances of a class | The receiver object itself |
| Common use in classes | Instance methods | Class methods |
| Works on any object? | Typically used in modules/classes | Yes |
| Affects ancestor chain? | Yes, for instance method lookup | Yes, via singleton class |
| Typical purpose | Shared object behavior | Class-level or object-specific behavior |
include vs prepend
| Feature | include | prepend |
|---|---|---|
| Method lookup priority | Class methods come before module methods | Module methods come before class methods |
| Common use | Add reusable behavior | Wrap or override behavior |
include/extend vs module singleton methods
| Pattern | Meaning |
|---|---|
def method_name inside a module | Defines a method that can be mixed in |
def self.method_name inside a module | Defines a method on the module object itself |
Example:
module ExampleModule
def mixed_in_method
"mixed in"
end
def self.module_method
"called on the module itself"
end
end
puts ExampleModule.module_method
# => called on the module itself
Cheat Sheet
# Define a module for mixing in
module MyModule
def hello
"hello"
end
end
# include => instance methods
class A
include MyModule
end
A.new.hello
# extend => methods on the object itself
class B
extend MyModule
end
B.hello
Rules to remember
includeadds module methods to instances of the classextendadds module methods to the receiver itself- classes are objects too, so
extendin a class body creates class methods extendcan be used on any object, not just classesdef self.nameinside a module defines a module-level method, not a mixin method
Quick checks
ClassName.ancestors
Shows modules included for instance lookup.
object.singleton_class.ancestors
Can help inspect methods added by extend.
Common pattern for both instance and class methods
module Example
def instance_method
"instance"
end
module ClassMethods
def class_method
"class"
end
end
def self.included(base)
base.extend(ClassMethods)
end
end
Edge case
If both the class and included module define the same method, the class version is used first.
FAQ
Is extend only for adding class methods in Ruby?
No. extend adds methods to any specific object. If that object is a class, the methods appear as class methods.
Why does include create instance methods?
Because the module is inserted into the class's ancestor chain for instance method lookup.
Can I use both include and extend with the same module?
Yes. Then the module's methods can be available both on instances and on the class object.
What is the difference between include and require in Ruby?
require loads a file. include mixes a module's methods into a class or module.
How do I add both instance and class methods from one module?
A common pattern is to include the module and, inside its included hook, extend a nested ClassMethods module.
Does include copy methods into the class?
Not exactly. Ruby uses the ancestor chain for method lookup rather than physically copying method definitions.
What happens if a class and an included module define the same method?
The class method takes priority over the included module method.
Mini Project
Description
Build a small Ruby example that models a class with shared instance behavior and shared class-level behavior. This project demonstrates the practical difference between include and extend in a realistic way.
Goal
Create a User class where instances can format their names, and the class itself can describe its role using module-based behavior.
Requirements
- Create one module for instance behavior
- Create one module for class-level behavior
- Use
includefor the instance behavior in theUserclass - Use
extendfor the class-level behavior in theUserclass - Show that instances and the class can call different methods
Keep learning
Related questions
Add a Default Value to an Existing Column in a Rails Migration
Learn how to add or change a default value on an existing database column using Rails Active Record migrations safely.
Calling a Class Method from an Instance in Ruby
Learn how to call a class method from an instance in Ruby using self.class, with examples, pitfalls, and practical usage patterns.
Calling an Overridden Monkey-Patched Method in Ruby
Learn how to call the original method when monkey patching in Ruby, including alias_method patterns, examples, pitfalls, and practical usage.