Prepend and Super for elegant Monkey Patching

Sebastian Royer
4 min readDec 5, 2017

--

While working through a few morning workout problems at The Flatiron School where I am currently completing a Web Development Immersive I recently ran into an interesting combination of features in Ruby’s inheritance scheme.

What caught my eye was #prepend in the Module class. It was slipped in as an alternative to #include, which is the normal way to compose an individual Module’s instance methods into a class you would like to use them in. While #include uses a normal inheritance scheme to allow a Class to run overwritten methods from the class they have been passed into first, #prepend inverts the order of inheritance to allow a Class to run its overwritten methods from the Module they were taken from first, effectively overriding the override (which seemed as silly as it sounds when I realized it.) More here.

How could this possibly be useful? I thought, out loud, to my desk mates and teachers. It turns out that there is a very specific way to make it useful and that is to use #prepend in the class to be modified in conjunction with #super in the Module methods. If you don’t know #super it is a function of inheritance and composition that allows an overwriting method to call “up” the inheritance chain to the Class or Module it is inheriting from and run the code in the class it is overwriting before continuing to run the code in the rest of the overwriting method. It is often used when monkey patching an existing method to tailor its functionality to the specific use case of an application or library.

If we include #super while overwriting a method we have composed into our class using #prepend, it will actually run the prepended version of the method first, with the prepending class as its ancestor, and then run the overwritten method’s code second. Importantly you do not have to edit the overwritten method’s code at all, allowing you to alter existing code functionality without writing any new code into that class, other than a prepend at it’s beginning. This allows you to monkey patch cleanly and efficiently without potentially breaking the code you are overwriting. It also gives the usual benefits of composition like identifiable error messaging and visible, reusable code alterations with a single source.

A simple and brief example follows. Pay careful attention to the return values as well as the outputs.

class Car
def go!
puts “Screech!”
end
end
# => :go!
test1 = Car.new
# => #<Car:0x007fb6ec8b2b30>
test1.go!
Screech!
# => nil
module Drivable
def go!
super
“Screech!”
end
end
end
# => :go!class Car
prepend Drivable
def go!
puts “Screech!”
end
end
# => :go!
test2 = Car.new
# => #<Car:0x007fb6ed119490>
test2.go!
Screech!
# => “Screech!”

As we can see, using the original Car class version of #go! outputs the text and returns nil. Once we #prepend the Drivable version of #go! it first outputs the text and then returns it. So we see that the #super call winds up calling to the class it is prepended into before the rest of the Drivable #go! method’s code is run. This can allow both the decorator and around patterns to be cleanly inserted.

The main point to take away is that with this pattern you can effectively overwrite your methods in your module and then mix them in as necessary, rather than #include them in your class and then overwrite them there.

A few examples I found where this has been used in production are available in the links below, mostly to replace the now deprecated alias_method pattern in Rails.

Bonus on why composition might be a better road than inheritance:

A last bit of truth: It’s all about the order of the inheritance chain. Before #include and #prepend its Foo < Bar. Afterwards its Pre < Foo < Inc < Bar.

--

--

Sebastian Royer

I’m writing a future that is up to us. I fell in love with the Apple+ my dad brought home when I was 6 and have been monkeying around in the wires ever since.