Ruby modules: Include vs Prepend vs Extend

Léonard Hetsch
5 min readJun 17, 2017

Modules are one of the most interesting features of Ruby. You can use them to attach specific behavior on your classes, and to organize your code using composition rather than inheritance. Here is a simple example:

Also, a lot of gems make use of modules to organize their code and ease up integration into your application. For example the Sidekiq gem provides the Sidekiq::Worker module to attach behavior to custom classes and use them as asynchronous workers components.

Though include is the most common way of importing external code into a class, Ruby provides also two other ways to achieve that: extend and prepend. However, they don’t have the same behavior at all, and these differences are often misunderstood by Ruby developers.

To understand how to use them, we must first have a deeper look into how Ruby is resolving methods to execute at runtime, using something called the ancestors chain.

The Ancestors chain

When a Ruby class is created, it holds a list of constant names which are its ancestors. They are all the classes that the class inherits from, and the modules they include. For example, by calling ancestors on the String class, we get the list of its ancestors:

> String.ancestors
=> [String, Comparable, Object, PP::ObjectMixin, Kernel, BasicObject]

We can see at the top of the chain BasicObject, which is the root of the Ruby object hierarchy, and also Object, the superclass of all classes, that also includes the Kernel module.

When we call the method object_id on a String instance (or any other class), Ruby will look up through the class ancestors to find the object_id method, and will eventually find it defined on the Object

Léonard Hetsch

Software engineer based in London / Technical coach @makersacademy / Previously @stuart @dicefm & @oncetheapp / Studied @gobelins_paris / Hungry learner.