Gems != Magic
16 Aug 2015Ruby gems can seem magical. Usually, one (or more accurately: thirty) solution to a problem exists in the form of a gem. Using gems is easy and intuitive. Simply add a line in the project root’s Gemfile
and run bundle install
. Then, either require
the name of the gem or, if using Ruby on Rails, start using the gem’s code immediately anywhere in the project. What could possibly go wrong?
Gems on gems on gems
Unchecked and unmanaged, a project’s Gemfile
might turn into something that looks like:
source 'https://rubygems.org'
gem 'linkbuilder'
gem 'http_helper'
gem 'the-color-red'
gem 'devise'
gem 'cancancancancan'
gem 'nokogiri'
gem 'crack'
# ...
# ....
# .....
gem 'cucumber'
gem 'avacado'
gem 'you-get-the-idea'
gem 'these-are-too-many-gems'
gem 'really'
It is very possible that all these gems do not have any adverse side effects. They might not even have any horrible monkey patches to String
or Object
. This post has more information on “Why do most Rails apps use so much memory per process?”.
Without being able to see inside of them, intrusive gems might be mixed into this mass and we would have no idea. At a glance, it is not immediately obvious how to differentiate between benign and malignant gems. It becomes infinitely easier to understand how gems interact if we remember that gems are not magic.
Gems are just Libraries
There it is! The rabbit is out of the hat. Somewhere, some amount of cats have been released from their respective bags. Gems are not magic silver bullets injected into a codebase. Instead they are nothing more than libraries of code. Gems are (hopefully) well encapsulated groups of files that amount to a (again hopefully) few pieces of helpful functionality. With this new understanding of what gems really are, it means that parsing, modifying, and creating gems is within reach. All that is left is to figure out how to pry them open.
Opening gems
Understanding gems is a great way to learn different design patterns and idiomatic Ruby conventions. Good gems have in-line documentation, great gems have comprehensive Github documentation. Github is the most common place to find the source code for gems and a large number of them have really great method and API documentation. This level of detail might be all that is required; however, for the more opaque gems, the bundle open
command is extremely helpful.
bundle open <gemname>
will use the system default text editor to open the contents of a gem. Since all gems are installed locally on the system, they should be available to open from a project’s root. If a default editor is not set, or the default is not desired, one can be added to the beginning of the command: EDITOR=vim bundle open <gemname>
.
A common starting place for a gem’s logic is in a file with the same name as the gem. Since most gems need to encapsulate their logic, a namespace or wrapper class is usually created with the same name as the gem. In this file it is equally common to find a list of required files or the entry point for the underlying logic. This file is usually in the root of the gem’s source or in a lib
directory.
In the validates_type root file:
Great! Now what?
Now, go out there and open up all the gems in the entire world! Read them, understand them, be one with the gems. Get a flavor for the different types of Ruby code that can exist. Then, after complete code nirvana has been achieved, submit a pull request to the gem’s source with some great additions. Or, place a few bindings in a few obscure methods to see how the code flows in and out of the gem. A master craftsman understands all of the tools in his toolbox, the same should be true for software.