The difference between include and extend in Ruby module

In Ruby, both include and extend are used to incorporate modules into classes, but they serve different purposes and are used in different contexts. Understanding the difference between these two methods is crucial for effectively organizing and utilizing code in Ruby applications.

Here’s a detailed explanation of the differences between include and extend:

include

Example

1
2
3
4
5
6
7
8
9
10
11
12
module Greetings
  def hello
    "Hello!"
  end
end

class Person
  include Greetings
end

person = Person.new
puts person.hello  # Output: "Hello!"

In this example, the hello method from the Greetings module is available as an instance method of the Person class. Any instance of Person can call hello.

extend

Example

1
2
3
4
5
6
7
8
9
10
11
module Greetings
  def hello
    "Hello!"
  end
end

class Person
  extend Greetings
end

puts Person.hello  # Output: "Hello!"

In this example, the hello method from the Greetings module is available as a class method of the Person class. The Person class itself can call hello, but instances of Person cannot.

Key Differences

Feature include extend
Scope Instance-level: adds instance methods Class-level: adds class methods
Usage Mixes in methods to be available for instances Adds methods to the class or object itself
Inheritance Methods are available to subclass instances Methods are not inherited by subclass instances
Purpose Share behaviors across instances of multiple classes Enhance the class or object with additional methods

When to Use include vs. extend

Combining include and extend

Sometimes, you might want to use both include and extend to provide both instance and class methods. You can do this by defining the instance methods directly in the module and using a nested module for class methods:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
module Greetings
  def hello
    "Hello from instance!"
  end

  module ClassMethods
    def hello
      "Hello from class!"
    end
  end

  def self.included(base)
    base.extend(ClassMethods)
  end
end

class Person
  include Greetings
end

person = Person.new
puts person.hello        # Output: "Hello from instance!"
puts Person.hello        # Output: "Hello from class!"