One of the greatest features that Ruby has to offer is its excellent support for metaprogramming. This concept is certainly not unique to Ruby, but Ruby is unique in the sheer amount support that it has for metaprogramming. And the Ruby community has definitely adopted it. You would be hard pressed to find a major Ruby library that does not make use of metaprogramming to some extent. Whether its a custom DSL, extensions upon core Ruby classes, or dynamically created methods, metaprogramming is everywhere in Ruby code.

While it is powerful, metaprogramming can get messy. Keeping track of all your extensions, where they apply, and when they’re loaded can introduce unnecessary complexity to an application. That’s where extensions_loader comes into play.

extensions_loader is a lightweight Ruby gem that takes the complexity out of creating Ruby extensions and applying them to existing classes.

Lets try an example. Lets say that I want to add the #average method to the Array class. Without using extensions_loader, I might do the following:

class Array
  def average
    inject { |sum, num| sum + num } / count
  end
end

This would work as expected, but its not exactly clear what’s happening here. A non-Rubyist would have no idea that this code actually extends upon the core Array class, rather than defining a new class.

Why don’t we try that with extensions_loader?

module ArrayAverage
  def average
    inject { |sum, num| sum + num } / count
  end
end

ExtensionsLoader.load!(Array => ArrayAverage)

Now, instead of directly reopening the Array class, we are defining a module with the clear purpose of averaging an Array. Then, with extensions_loader, we’re cleanly providing that functionality to the Array core class.

What if we wanted to add another method to Array, say #to_sentence?

module ArrayAverage
  def average
    inject { |sum, num| sum + num } / count
  end
end

module ArraySentence
  def to_sentence
    join(', ')
  end
end

ExtensionsLoader.load!(
  Array => [ArrayAverage, ArraySentence]
)

By providing an Array of Modules rather than a single Module, we can specify a number of extensions to load onto the Array class. It’s very clear what’s happening here, and its super easy to remove specific pieces of functionality. Just remove the element!

Hopefully extensions_loader can clean up your Ruby monkeypatching and make it easier to understand your Ruby metaprogramming code!