Rails Gemfile Teardown - 2014

What’s the first thing you look at when you see the source code of a Rails project?

For me, it’s the Gemfile. Think about it…there’s very few other files that contain so much information. It describes the building blocks of the application. And at times, you can even see specific features of the application.

A Gemfile also includes hints about preference and style. And style is something most Ruby developers are very passionate about. It doesn’t take long to find the story of a Rubyist describing their “love at first sight” experience with the language. It’s hard to find another file in a Rails project that’s so telling.

A year ago, I wrote about the Ruby gems I regularly use in my Rails applications. Because technology and the tools we use change so fast, I thought it’d be interesting to take a look at one of my more recent Gemfiles to see what’s changed.

Rails Templates

As I mentioned in the last Gemfile post, I tend to write a bunch of small applications sprinkled around some larger ones. Despite the size of the project, I feel like I’ve honed in a set of Ruby gems that feel comfortable and productive for me and my workflow.

Knowing the act of bootstrapping a Rails project is sometimes tedious, I took some time to build a Rails template around the gems and patterns I commonly use. I’ll definitely be writing about this experience in the future since there seems to be very little discussion about it.

In short, extracting my preferences to a template has been a HUGE time saver. It no longer feels like a burden to run rails new. I can jump right in and have a consistent set of tools that enable me to be productive within a few minutes.

My 2014 Gemfile

The Gemfile below is one of the larger projects I worked on this year. I thought it’d give a good sense of some of my more practical everyday preferences, along with some feature-specific choices for this particular application.

source 'https://rubygems.org'

ruby '2.1.4'

gem 'rails', '4.1.8'
gem 'pg'
gem 'sass-rails', '~> 4.0.3'
gem 'uglifier', '>= 1.3.0'
gem 'coffee-rails', '~> 4.0.0'
gem 'jquery-rails'
gem 'turbolinks'

gem 'bcrypt-ruby', '~> 3.1.2'

group :development, :test do
  gem 'pry'
end

group :test do
  gem 'selenium-webdriver'
  gem 'capybara'
  gem 'timecop'
  gem 'mocha'
end

group :development do
  gem 'quiet_assets'
  gem 'spring'
  gem 'bullet'
  gem 'stripe_tester', '~> 0.1.0'
end

group :production, :demo do
  gem 'rails_12factor'
  gem 'heroku-deflater'
end

gem 'font-awesome-rails'
gem 'unicorn'
gem 'bootstrap-sass'
gem 'sidekiq', require: 'sidekiq/web'
gem 'sinatra'
gem 'local_time'
gem 'gravatar_image_tag'
gem 'so_meta'
gem 'chronic'
gem 'recurrence'

gem 'premailer-rails'

gem 'momentjs-rails'
gem 'bootstrap3-datetimepicker-rails'
gem 'bootstrap-switch-rails'
gem 'bootstrap-wysihtml5-rails'
gem 'bootstrap-select-rails'
gem 'autosize-rails'

gem 'aws-sdk'

gem 'html-pipeline'
gem 'rinku'

gem 'newrelic_rpm'
gem 'doc_raptor'
gem 'stripe'
gem 'jquery-ui-rails'
gem 'active_model_serializers'
gem 'rubyzip'
gem 'render_anywhere', require: false
gem 'pusher'
gem 'filepicker-rails'
gem 'memcachier'
gem 'dalli'
gem 'intercom-rails'

A few comments:

  • I’ve standardized on Postgres as the database for my apps, even in development. It’s reliable and allows me to be sure that the code I write will work the same way in production, since I tend to deploy most of my apps to Heroku.

  • I leave turbolinks on. Judging from recent posts and comments within the community, this will probably one of the more controversial decisions.

    If I’m being honest, my first experience with Turbolinks wasn’t great. And by “wasn’t great”, I mean — it broke EVERYTHING! But the good news was that it brought to light the fact that I sucked at javascript. At the time, I was capable of writing just enough to modify form behavior or fade in an DOM element.

    The time had come to level up on my javascript skills. I was able to improve my javascript and also do it in a way that can took full advantage of the benefits that Turbolinks offers. Since that time, I’ve left Turbolinks on and no longer had to worry that my client-side code will stop working after clicking through a few application links.

  • I’ve standardized on using has_secure_password for authentication. I previously used devise, but found the extra features are no longer worth the additional complexity. has_secure_password provides me reliable authentication patterns that are simple to understand and maintain. Hence the need for bcrypt in the Gemfile above.

  • As for my test environment, I’ve written about my switch to Minitest and fixtures. I’m still just as happy with that decision as the time I wrote about it. I’ve seen Rspec go through a variety of API changes since then, and thankful I no longer have to worry about updating my test suite every couple months. I continue to find value in capybara and include mocha for the times Minitest’s stubbing and mocking isn’t enough (I’ve been meaning to dig in to the places I use mocha. I’m guessing if the code was better, I probably wouldn’t need it at all).

  • bullet is a killer gem for tracking down performances issues. It’s saved me countless hours of debugging.

  • The inclusion of spring in Rails 4.1 is great. I realize it’s a bandaid in some respects, but waiting for the environment to load on every test run is a drag. I’ve found that because my tests are so responsive when spring is working properly, it encourages me to run my tests more often. Once setup, it works well and only in rare cases has not reloaded when it should have.

  • I generally always include bootstrap and font-awesome in my projects. Being a non-designer, it helps me get something on the screen faster, even if it’s not the final design.

  • I continue to use unicorn. It’s been around for so long and continues to be competitive in benchmarks against other Ruby web servers. I tested Passenger in a few applications, but got scared off when it printed the entire environment to the screen in production on Heroku on an exception. I’m told there are ways around this with some non-trivial configuration, but I think it’s a bizarre default and isn’t conducive to my workflow.

  • For the apps that need background processing, sidekiq continues to be my goto when a separate worker is necessary. I generally mount Sidekiq’s web UI to provide insight to the state of the jobs, which is why sinatra is included.

  • I’ve written about putting together a gem to render relative timestamps on the client side. While I’d love to sit here and tell you I use it, I don’t. Basecamp’s local_time gem is exceptional for that need and I’m pretty sure we can count on it being updated and maintained well going forward (one of the biggest changes in my mindset for including a new gem).

  • This particular app has some pretty hairy time calculations and scheduling. It’s not something I was very experienced with prior, but found value in the combination of chronic and recurrence. Both make the process of targeting a specific datetime and scheduling something in the future relatively simple.

  • I included a number of bootstrap related javascript gems (bootstrap3-datetimepicker-rails, bootstrap-switch-rails, bootstrap-switch-rails, bootstrap-select-rails). All are little more than a Rails engine that exposes the appropriate javascript and stylesheets to the asset pipeline. These are particularly dependent on the project. I’d normally not start by including anything like this. Side note - I could’ve copied the relevant assets to vendor/assets rather than requiring a gem that does the same. In a few cases, some added view helpers as well.

  • I’ve standardized on using New Relic to collect application metrics and exceptions.

  • It shouldn’t be a surprise that stripe is the payment processor I reach for when I’m in control. It’s super developer-friendly and, at this point, I’ve done enough that integration is not much more than a copy/paste from other apps. I recently started using stripe_tester in the test environment. It’s been great for stubbing out calls to Stripe so the test suite continues to be performant. It also allows me to setup some unique edge-case data coming from Stripe so I can protect users from ending up in a crappy state.

  • I generally reach for active_model_serializers anytime I need a json response that contains more than a simple hash (in which case I’d continue to render it in the controller response). I’ve used the view equivalent solutions a few times (jbuilder, etc.) and they worked ok too, but for whatever reason, active_model_serializers does it for me.

The rest are very use case-specific. And in general, the defacto solution for each (pusher for real-time features, dalli for memcached, etc.).

Summary

I’m happy with my current toolkit. This doesn’t mean I’m not on the lookout for shiny new things, but I’m generally a little more cautious about replacing something reliable, even if it doesn’t do everything under the sun.

Even though Ruby makes it easy to include third party libraries, it doesn’t mean we always should. As developers, we inherit the stability of the dependencies we include. Even though a gem’s code might be locked away behind a separate git repository, it likely has the same holes and complexities that we’re worried about in our applications. And perhaps, even more…

Ruby toolbox is a great resource when searching for a gem. I generally consider the number of downloads, age of the project and development activity when deciding which one to go with.

What have your favorite gems been this year?

Build a Ruby Gem

Ruby gems are the building blocks of Ruby/Rails applications. If you haven’t built one yourself, there’s no better time to start. Github makes it extremely to contribute to existing gems and sometimes that’s the easiest way to get started contributing to open source. My book, Build a Ruby Gem, includes everything you to need to get started building a Ruby gem.