Blog

Extract your common Ruby gems for increased maintainability

After six years of writing Rails apps, for clients as well as side projects (and not-so-side projects), I started seeing a clear pattern in my Gemfiles, namely a bunch of gems I used over and over again.

Well, actually I probably started seeing those patterns already on the third or fourth Rails app, but by now I can be fairly certain that there are some gems that I will want to use in every project I work on.

I used to define my gem dependencies very explicitly:

gem 'devise', '3.2.4'

I never liked the ~> syntax since I wanted to see in my Gemfile exactly which gem versions the app was using, and I didn't trust other developers to always use semantic versioning. :)

This meant that, when a new version of devise was released for example, I had to go through all of my apps, find those that use devise, and update the dependency one by one.

Now I realized most gems (the ones I include in my commons gems at least) do use semantic versioning and defining my gem dependencies using ~> actually has a lot of advantages.

Pull out

So I started to pull out those common gems and put them in a separate Git repo. I add this repo as a Git submodule in each of my apps, and require the included Gemfiles in my project's Gemfile like so:

%w(
  common-gems/rails/Gemfile
  common-gems/redis/Gemfile         # optional
  common-gems/sidekiq/Gemfile       # optional
  common-gems/testing/Gemfile       # optional
).each do |gemfile|
  instance_eval(File.read(gemfile))
end

So far this has served me very well, but if it becomes too cluttered or confusing I might revisit it in the future.

Would love to hear from other developers in the comments what they thing about this approach!

Discuss this post on Hacker News

Ideas? Constructive criticism? Think I'm stupid? Let me know in the comments!