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.
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.
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
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.
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.
turbolinkson. Judging from recent posts and comments within the community, this will probably one of the more controversial decisions.
I’ve standardized on using
has_secure_passwordfor authentication. I previously used devise, but found the extra features are no longer worth the additional complexity.
has_secure_passwordprovides me reliable authentication patterns that are simple to understand and maintain. Hence the need for
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
mochafor 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).
bulletis a killer gem for tracking down performances issues. It’s saved me countless hours of debugging.
The inclusion of
springin 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
springis 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
font-awesomein 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,
sidekiqcontinues 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
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
recurrence. Both make the process of targeting a specific
datetimeand scheduling something in the future relatively simple.
vendor/assetsrather 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
stripeis 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_testerin 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_serializersanytime I need a
jsonresponse 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_serializersdoes 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.).
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.