Ruby’s Prepend: How is it useful?

Timi Ajiboye
chunks of code*
Published in
4 min readDec 28, 2018

With a real world example

This article introduced me to Prepend. It does a really good job of explaining the keywords below & the ancestor hierarchy. As such it’s a good idea to read it before mine. I decided to write this to show my real world use-case of Prepend, in hopes that it could help someone else understand better.

There are a few ways to modularize code in classes (or modules) in Ruby, namely:

Include

class Human
include Bipedalism

What this does is adds the methods in Bipedalism to the Human class as instance methods.

Extend

class Human
extend Bipedalism

What this does is adds the methods in Bipedalism to the Human class as class methods.

Prepend

To understand how Prepend works, it’s important to know what the ancestors chain is.

If you’re familiar with inheritance (in any language), this should immediately make sense.

Ancestor’s chain

Functionality (methods) is shared in Ruby (and other languages) via inheritance.

When you call a method on an object, the Ruby interpreter tries to find that method definition in it’s class, if it doesn’t find it, it checks the class it inherits from (superclass), and so on till it does.

When you use Include in a module, what the Ruby interpreter does is to inserts the included module right above the current class in the ancestor chain.

class Human
include Bipedalism

This means that Bipedalism is the parent class of Human.

However, what Prepend does is slightly different. It puts the prepended module below the current class in the ancestor chain.

class Human
prepend Bipedalism

This means that Human is the parent class of Bipedalism.

At first, Prepend seemed weird and I wondered what it could possibly be useful for, until I figured out this use case:

An Example

In BuyCoins’ back-end, we have a concept called a Bridge. And we have many “Bridges”.

For a class to be a Bridge (in our codebase), it needs to respond to certain method calls. Let’s just imagine that there’s only 2 of them; get_address & balance.

Every class that is meant to be a Bridge will need to implement those methods (because duck typing).

At this point, everything is relatively simple. I could create FirstBridge & SecondBridge as follows:

class FirstBridge
def get_address
# do whatever
end

def
balance
# do some magic
end
end

class
SecondBridge
def get_address
# do whatever
end

def
balance
# do some magic
end
end

I however had this requirement that made things a bit difficult. I wanted it such that a validation method (validate_supported_currency) is first called every time any method (get_address, balance) in any Bridge is called.

One way to do this would be to copy and paste this validation method in every Bridge class. And then manually invoke it in all the methods.

class SecondBridge

def get_address
validate_supported_currency
# do the things to get address
end

def
balance
validate_supported_currency
# do the magic
end

def
validate_supported_currency
raise Exceptions::UnsupportedCurrencyError if conditions_not_fulfilled
end
end

This is a stressful solution, because it requires me to repeatedly define validate_supported_currency and then remember to make sure it’s called in every method.

One other option would be to define a Bridge module that defines validate_supported_currency and then I could include that in every class that’s meant to be a Bridge.

module Bridge

def validate_supported_currency
raise Exceptions::UnsupportedCurrencyError if conditions_not_fulfilled
end

end

class
FirstBridge
include Bridge

def get_address
validate_supported_currency
# do the things to get address
end

def
balance
validate_supported_currency
# do the magic
end

end

This solves the problem of having to define validate_supported_currency repeatedly but I still have to remember to invoke it in every single method of every Bridge class that I create.

To solve that, I decided to use prepend. This means that I first needed to make some additions to the Bridge module.

module Bridge

def get_address
validate_supported_currency
super
end

def
balance
validate_supported_currency
super
end

def
validate_supported_currency
raise Exceptions::UnsupportedCurrencyError if conditions_not_fulfilled
end

end

super simply calls the method of the same name in the parent class of the current class.

Let’s look at get_address, what this means is that after calling validate_supported_currency Ruby will try to see if our current object has a parent class/module with get_address defined and then invoke it if it does. You can read more about super and overriding methods here.

So how do we get this to work in our actual Bridge classes? Simple:

class AnotherBridge
prepend Bridge

def get_address
# do the tings fam
end

def
balance
# magic time
end

end

And that’s it! By simply prepending Bridge, every time get_address or balance is called, validate_supported_currency will be called first before running the code that’s actually defined in the methods themselves.

This is because (as explained above) prepend makes AnotherBridge the parent class of Bridge.

As such, when get_address is called, the Ruby interpreter will invoke the get_address as is defined in Bridge first. And this invokes validated_supported_currency.

Then we call super in the next line which then invokes the get_address defined in AnotherBridge (the parent class).

That’s all for today! Go forth and prepend!

--

--

Timi Ajiboye
chunks of code*

I make stuff, mostly things that work on computers. Building Gandalf.