Bird
Raised Fist0
Rubyprogramming~15 mins

Include for instance methods in Ruby - Deep Dive

Choose your learning style10 modes available
Overview - Include for instance methods
What is it?
In Ruby, the 'include' keyword is used to add instance methods from a module into a class. When you include a module, all its instance methods become available as if they were defined directly inside the class. This helps share common behavior across different classes without repeating code. It is a way to reuse code by mixing in methods from modules.
Why it matters
Without 'include', you would have to copy and paste the same methods into every class that needs them, which is inefficient and error-prone. 'Include' solves this by letting you write methods once and share them easily. This makes your code cleaner, easier to maintain, and reduces bugs caused by duplicated code. It also supports a flexible design where behavior can be mixed into classes as needed.
Where it fits
Before learning 'include', you should understand Ruby classes, methods, and modules basics. After mastering 'include', you can explore 'extend' for class methods, and advanced topics like mixins, method lookup, and Ruby's inheritance model.
Mental Model
Core Idea
Including a module in a class copies the module’s instance methods into the class, making them available to all instances as if defined there.
Think of it like...
Imagine a toolbox (module) full of tools (methods). Including the toolbox in your workshop (class) means every worker (instance) in that workshop can use those tools anytime without owning them individually.
Class
┌───────────────┐
│               │
│  Instance     │
│  Methods      │
│  + Included   │
│  Module's     │
│  Methods      │
└───────────────┘
   ↑
   │
Include Module
┌───────────────┐
│ Module        │
│ Instance      │
│ Methods       │
└───────────────┘
Build-Up - 7 Steps
1
FoundationUnderstanding Ruby Modules
🤔
Concept: Modules are containers for methods that can be shared across classes.
In Ruby, a module is like a box where you put methods that you want to reuse. Modules cannot create objects themselves but can be included in classes to share behavior. For example: module Greetings def hello "Hello!" end end
Result
You have a module named Greetings with one method hello.
Knowing what a module is sets the stage for understanding how to share methods without inheritance.
2
FoundationDefining Instance Methods in Modules
🤔
Concept: Methods inside modules are instance methods when included in classes.
Inside a module, methods you define are instance methods. They become available to instances of any class that includes the module. For example: module Greetings def hello "Hello!" end end class Person include Greetings end p = Person.new p.hello #=> "Hello!"
Result
Calling p.hello returns "Hello!" because the method is included as an instance method.
Understanding that module methods become instance methods in the including class explains how behavior is shared.
3
IntermediateHow Include Affects Method Lookup
🤔Before reading on: do you think included module methods override class methods or vice versa? Commit to your answer.
Concept: Including a module inserts it into the class’s method lookup chain just above the class itself.
When Ruby looks for a method, it checks the object's class first, then any included modules in reverse order of inclusion, then the superclass. This means if a class defines a method with the same name as an included module, the class’s method is used instead. Example: module Greetings def hello "Hello from module" end end class Person include Greetings def hello "Hello from class" end end p = Person.new p.hello #=> "Hello from class"
Result
The class method overrides the module method because it is found first in the lookup chain.
Knowing the method lookup order helps avoid unexpected method overrides and bugs.
4
IntermediateIncluding Multiple Modules and Order
🤔Before reading on: If you include two modules with the same method, which one is called? The first or the last included? Commit to your answer.
Concept: When multiple modules are included, the last included module’s methods take precedence in method lookup.
Ruby inserts included modules into the lookup chain in the order they are included, with the last included module checked first. Example: module A def greet "Hello from A" end end module B def greet "Hello from B" end end class Person include A include B end p = Person.new p.greet #=> "Hello from B"
Result
The greet method from module B is called because it was included last.
Understanding inclusion order prevents confusion when mixing multiple modules with overlapping methods.
5
AdvancedUsing Include for Code Reuse and Mixins
🤔Before reading on: Do you think 'include' can add both instance and class methods? Commit to your answer.
Concept: Include adds instance methods; to add class methods, other techniques are needed.
Include is designed to add instance methods only. To add class methods, Ruby programmers often use 'extend' or define methods inside a module’s 'self.included' hook. Example: module Greetings def instance_hello "Hello instance" end module ClassMethods def class_hello "Hello class" end end def self.included(base) base.extend(ClassMethods) end end class Person include Greetings end p = Person.new p.instance_hello #=> "Hello instance" Person.class_hello #=> "Hello class"
Result
Instance methods come from include; class methods come from extending inside the included hook.
Knowing include only adds instance methods clarifies how to properly share class-level behavior.
6
AdvancedInclude vs Inheritance Differences
🤔
Concept: Include mixes in methods without creating a parent-child class relationship.
Inheritance creates a strict parent-child link between classes, sharing all methods and allowing overrides. Include mixes in methods from modules without changing the class hierarchy. This allows sharing behavior across unrelated classes. Example: class Animal def speak "Animal sound" end end module Walkable def walk "Walking" end end class Dog < Animal include Walkable end class Robot include Walkable end Dog.new.walk #=> "Walking" Robot.new.walk #=> "Walking"
Result
Both Dog and Robot can walk, but only Dog inherits from Animal.
Understanding this difference helps design flexible systems using mixins instead of rigid inheritance.
7
ExpertInternal Mechanics of Include and Ancestors Chain
🤔Before reading on: Do you think 'include' copies methods or changes the class’s ancestors chain? Commit to your answer.
Concept: Include inserts the module into the class’s ancestors chain, affecting method lookup without copying methods.
When you include a module, Ruby inserts it into the class’s ancestors chain as a hidden proxy class. This means methods are not copied but looked up through this chain. You can see this with: class Person include Greetings end Person.ancestors #=> [Person, Greetings, Object, Kernel, BasicObject] This chain controls how Ruby finds methods when called on instances.
Result
The module appears in the ancestors chain, influencing method lookup order.
Knowing include manipulates the ancestors chain explains method resolution and why method overrides behave as they do.
Under the Hood
When you use 'include', Ruby inserts the module into the class’s ancestors chain just above the class itself. This means Ruby does not copy methods into the class but changes the order Ruby searches for methods when you call them on an instance. The module acts like a hidden superclass proxy. This allows multiple modules to be included and searched in order, enabling flexible method sharing and overriding.
Why designed this way?
Ruby’s design favors flexibility and simplicity. Instead of copying methods, which wastes memory and complicates updates, inserting modules into the ancestors chain allows dynamic method lookup and easy method overriding. This design supports mixins, a powerful alternative to single inheritance, enabling code reuse without rigid class hierarchies.
Class Person
┌─────────────────────────────┐
│                             │
│  Instance methods            │
│  + Included modules          │
│                             │
└─────────────┬───────────────┘
              │
              ▼
Ancestors chain:
[Person] -> [Greetings Module] -> [Object] -> [Kernel] -> [BasicObject]
Myth Busters - 4 Common Misconceptions
Quick: Does 'include' add class methods to the class? Commit to yes or no.
Common Belief:Including a module adds both instance and class methods to the class.
Tap to reveal reality
Reality:'Include' only adds instance methods. Class methods require 'extend' or other patterns.
Why it matters:Assuming 'include' adds class methods leads to errors when calling class methods that don't exist, causing runtime failures.
Quick: If a class and included module have the same method, which one runs? Commit to your answer.
Common Belief:The module’s method always overrides the class’s method.
Tap to reveal reality
Reality:The class’s own method overrides the included module’s method because it is found first in the lookup chain.
Why it matters:Misunderstanding this causes confusion when debugging why a method from the class is called instead of the module’s.
Quick: Does including a module copy its methods into the class? Commit to yes or no.
Common Belief:Including a module copies its methods into the class, duplicating code.
Tap to reveal reality
Reality:Including inserts the module into the method lookup chain without copying methods.
Why it matters:Thinking methods are copied can lead to wrong assumptions about memory use and method updates.
Quick: Can you include a module multiple times in the same class? Commit to yes or no.
Common Belief:Including the same module multiple times adds duplicate methods and causes errors.
Tap to reveal reality
Reality:Ruby ignores duplicate includes of the same module in a class to prevent redundancy.
Why it matters:Believing duplicates cause errors may lead to unnecessary code complexity or workarounds.
Expert Zone
1
Including a module creates an anonymous proxy class in the ancestors chain, which can affect method lookup performance subtly.
2
The order of included modules matters deeply when multiple modules define the same method; last included wins in lookup order.
3
Using 'prepend' instead of 'include' inserts the module before the class in the lookup chain, changing override behavior.
When NOT to use
Avoid using 'include' when you need to add class methods; use 'extend' instead. Also, if you require strict inheritance behavior or state sharing, prefer subclassing. For complex method resolution control, consider 'prepend' or explicit delegation.
Production Patterns
In production Ruby code, 'include' is widely used to share common instance methods like logging, validation, or formatting across unrelated classes. Frameworks like Rails use modules with 'include' to add features to models and controllers. Developers often combine 'include' with hooks like 'self.included' to add class methods dynamically.
Connections
Inheritance
Alternative approach to sharing behavior
Understanding 'include' clarifies how Ruby supports flexible code reuse beyond rigid parent-child class inheritance.
Mixin Pattern (Software Design)
Direct implementation of mixins in Ruby
Knowing Ruby's 'include' helps grasp the mixin design pattern, which promotes composition over inheritance.
Trait Composition (Programming Languages)
Similar concept in other languages for code reuse
Recognizing 'include' as a form of trait composition connects Ruby to broader programming language design ideas.
Common Pitfalls
#1Expecting included modules to add class methods directly.
Wrong approach:module M def self.class_method "Hi" end end class C include M end C.class_method # Error: undefined method
Correct approach:module M def instance_method "Hi" end module ClassMethods def class_method "Hi" end end def self.included(base) base.extend(ClassMethods) end end class C include M end C.class_method #=> "Hi"
Root cause:Misunderstanding that 'include' only adds instance methods, not class methods.
#2Including modules in wrong order causing unexpected method overrides.
Wrong approach:class C include A include B end # Both A and B define method foo c = C.new c.foo # Calls B's foo unexpectedly
Correct approach:class C include B include A end c = C.new c.foo # Calls A's foo as intended
Root cause:Not realizing that the last included module takes precedence in method lookup.
#3Trying to call module methods directly on class after include.
Wrong approach:module M def greet "Hi" end end class C include M end C.greet # Error: undefined method
Correct approach:c = C.new c.greet #=> "Hi"
Root cause:Confusing instance methods added by include with class methods.
Key Takeaways
'include' mixes instance methods from a module into a class, making them available to instances.
Included modules are inserted into the class’s method lookup chain, not copied, enabling flexible method resolution.
Class methods are not added by 'include'; use 'extend' or hooks to add class-level behavior.
The order of included modules affects which methods are called when names overlap.
Understanding 'include' helps design reusable, maintainable Ruby code without relying solely on inheritance.

Practice

(1/5)
1. What does the include keyword do in Ruby when used inside a class?
easy
A. It deletes all methods from the class.
B. It adds the module's methods as class methods to the class.
C. It creates a new module inside the class.
D. It adds the module's methods as instance methods to the class.

Solution

  1. Step 1: Understand the role of include

    The include keyword is used to add methods from a module into a class.
  2. Step 2: Identify how methods are added

    When a module is included, its methods become instance methods of the class, meaning objects of the class can call them.
  3. Final Answer:

    It adds the module's methods as instance methods to the class. -> Option D
  4. Quick Check:

    Include = instance methods added [OK]
Hint: Include adds module methods as instance methods [OK]
Common Mistakes:
  • Confusing include with extend (which adds class methods)
  • Thinking include creates a new module
  • Assuming include removes existing methods
2. Which of the following is the correct syntax to include a module named Greetings inside a class Person?
easy
A. class Person; include Greetings; end
B. class Person; extend Greetings; end
C. class Person; include(Greetings); end
D. class Person; use Greetings; end

Solution

  1. Step 1: Recall correct syntax for including modules

    In Ruby, to add instance methods from a module, use include ModuleName inside the class body without parentheses.
  2. Step 2: Check each option

    class Person; include Greetings; end uses include Greetings correctly. class Person; extend Greetings; end uses extend which adds class methods, not instance methods. class Person; include(Greetings); end uses parentheses which is not standard syntax. class Person; use Greetings; end uses use which is invalid in Ruby.
  3. Final Answer:

    class Person; include Greetings; end -> Option A
  4. Quick Check:

    Include syntax = include ModuleName [OK]
Hint: Use 'include ModuleName' without parentheses [OK]
Common Mistakes:
  • Using extend instead of include
  • Adding parentheses after include
  • Using invalid keywords like 'use'
3. What will be the output of the following Ruby code?
module Talk
  def speak
    "Hello!"
  end
end

class Dog
  include Talk
end

puts Dog.new.speak
medium
A. NoMethodError
B. Hello!
C. speak
D. nil

Solution

  1. Step 1: Understand module inclusion

    The module Talk defines an instance method speak. Including it in Dog adds speak as an instance method of Dog.
  2. Step 2: Trace the method call

    Creating a new Dog object and calling speak will execute the method from Talk, returning "Hello!".
  3. Final Answer:

    Hello! -> Option B
  4. Quick Check:

    Included method called = "Hello!" [OK]
Hint: Included module methods become instance methods [OK]
Common Mistakes:
  • Expecting NoMethodError because of missing method
  • Confusing instance and class methods
  • Thinking output is method name or nil
4. Identify the error in the following Ruby code:
module Walk
  def walk
    "Walking"
  end
end

class Person
  extend Walk
end

puts Person.new.walk
medium
A. NoMethodError because walk is not an instance method
B. SyntaxError due to extend usage
C. No error, outputs "Walking"
D. TypeError because module cannot be extended

Solution

  1. Step 1: Understand extend vs include

    Using extend Walk adds module methods as class methods, not instance methods.
  2. Step 2: Analyze method call

    Person.new.walk calls walk on an instance, but walk is only a class method here, so it raises NoMethodError.
  3. Final Answer:

    NoMethodError because walk is not an instance method -> Option A
  4. Quick Check:

    Extend adds class methods, instance call fails [OK]
Hint: Extend adds class methods; instance calls fail [OK]
Common Mistakes:
  • Confusing extend with include
  • Expecting no error on instance method call
  • Thinking extend causes syntax or type errors
5. Given the module and classes below, what will puts Cat.new.sound output?
module AnimalSounds
  def sound
    "Generic sound"
  end
end

class Dog
  include AnimalSounds
  def sound
    "Bark"
  end
end

class Cat
  include AnimalSounds
end
hard
A. Bark
B. NoMethodError
C. Generic sound
D. nil

Solution

  1. Step 1: Check method definitions in classes

    Class Dog overrides sound method with "Bark". Class Cat does not override it.
  2. Step 2: Determine method lookup for Cat instance

    Since Cat includes AnimalSounds and does not override sound, calling sound on Cat.new uses the module's method returning "Generic sound".
  3. Final Answer:

    Generic sound -> Option C
  4. Quick Check:

    Included method used if no override [OK]
Hint: Class method overrides module method if defined [OK]
Common Mistakes:
  • Assuming Cat uses Dog's sound method
  • Expecting NoMethodError for missing method
  • Confusing instance and class methods
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard