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:speak- includes the module
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
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
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
|| {}
setting ,
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:
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 |
|---|
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.
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?
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
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.
Difference Between require and include in Ruby
Learn the difference between require and include in Ruby, when to load a file, and when to mix module methods into a class.
Fixing Ruby Gem Native Extension Errors: mkmf.rb Can't Find Header Files for Ruby
Learn why Ruby gem installs fail with missing ruby.h, how native extensions work, and how to fix header file errors on Linux servers.