Robert Heaton

Software Engineer /
One-track lover / Down a two-way lane

How to save 1 day/year of quality Rails time

13 Feb 2013

Once there was a boy who was given a brand new open source Ferrari, entirely for free. He crashed the Ferrari into a patisserie, setting it on fire and covering it in coconut flakes. But he simply ran “rails g new Ferrari”, and a new one appeared! The boy was ecstatic, and so he immediately drove the new Ferrari straight into the same patisserie, causing $500,000 of further damage and wounding a small child. But he nipped back home, ran “rails g new Ferrari” again and there, against all the guidelines of the DMV, appeared another one.

But 58 bakery burnouts later the child grew irritated. Whilst it was nice that he got a generic car that worked for a wide range of people for free, he always set up the seat in the same place, adjusted the wing mirrors in the same way and put the same brand of gloves in the glove compartment. Why should he have to do this EVERY SINGLE TIME he wanted to setup a new car? He went looking for answers.

Rails is pretty much unrivalled in its ability to work immediately, straight out of the box. There is very little tedious, repetitive admin to be done before you have something that displays what you expected on a web page, and so starting a new project or experiment has very low activation energy. But there have been so many further fantastic plain Ruby and Rails-specific gems written that many of them have become indispensable. Putting to one side paranoia about how it doesn’t scale over a bajillion users and slightly-more-reasonable-paranoia about the risks of not knowing the ins-and-outs of your auth system, you need a very good reason not to immediately slap in the Devise/CanCan tag team (or similar but marginally more hipster alternative if you must). And there is absolutely no acceptable reason to not be using BetterErrors; you’re going to spend 85% of your time staring at an error screen, so it might as well be a good one.

Whilst it would obviously make absolutely no sense for these to be included with Rails itself, as far as I am concerned they might as well be. I realised this properly yesterday when I sat down to hack together a experimental RSS pulling system. I’m sure you’ve been in a similar place. You start excitedly “rails g model”-ing and researching RSS gems, but then grind to a halt when you come to do login. You need Devise – go and get that. Might as well get CanCan too. Oh crap you don’t have HAML installed yet. Is it “haml” or “haml-rails”? Might as well throw Bootstrap in there, pretty sure that’s “twitter-bootstrap-rails”. A first pass through gems that you will probably always need might give you:

Bootstrap, SimpleForm, Devise, CanCan, Haml, Pry, Squeel, DelayedJob, DelayedJobActiveRecord, FriendlyId, FactoryGirl, Roadie, Symbolize, BetterLogging, PG, RSpec, Capybara, CapybaraWebkit, DatabaseCleaner, BetterErrors, Fivemat, MailView

Maybe you won’t need all of them, but you probably will, and there are doubtless many others that you have forgotten. It might get so tedious remembering the exact format of the gem names that you copy over the gemfile from your big badass startup project and just delete all the domain specific ones. But then one bundle install later and you’re good to go.

Except obviously you’ve got to run some generators. Depending on how methodical you are feeling this will probably be a process of rails s, error, run generator, get the syntax wrong, look up syntax on Github, run generator, repeat. This is a tedious and frustrating process (there are at least 6 non-test generators required for the list above), and will repeatedly break your flow when you are busy trying to be a visionary. You will no doubt forget to run the Rspec and FactoryGirl ones when the time comes too.

But there is more. I use a pattern of storing API keys and the like in config/config.yml (http://railscasts.com/episodes/85-yaml-configuration-file), and you should too. This will need creating and loading, and there’s a good chance you’ll have to look up the exact format of the YAML loading line. Depending on how anal you are about these things, sooner or later you will need to convert application.html.erb into application.html.haml. You will also at some point need a PagesController for your static pages. You’ll need a views folder for this, and will realistically always want a home action and a corresponding route and view. You’re probably going to want a NotificationMailer and another views folder for it. You’ll want to setup Roadie’s CSS file to be included and inlined at this point. I like making all my Mailers inherit from my own BaseMailer class so you can insert any methods or setting you want them all to share. You’ll always want authenticate_user! as a before_filter in ApplicationController. You’ll need to delete public/index.html. I like having a /extras folder. You can be pretty sure that you will want “can [:edit, :update, :destroy], User, user_id: user.id” in your abilities.rb file too and will want to send them an email when they sign up, although by this point you’ve probably reached the point of diminishing returns.

Not all of this stuff is needed to get your teeth stuck into the fun parts of writing v0.1, but a lot of it is, and it is pretty much all needed before your alpha-release can be deployed to Heroku. If the project continues past day 1 then omitting any of the above is almost definitely just laziness.

So the next time you want to start an exciting new Rails project, do future-you a favour and first create v0.1 of the generic setup that you know you trudge through every time. Include all the gems that you know you will always need, run their generators, create the repetitive infrastructure that all your projects will be aggressively hamstrung without. It took me somewhere between 30 and 40 minutes to do most of the above, so I figure that if I start approx 1 new project or experiment per month then I’ll be saving between 6-8 hours per year. But this relatively trivial time accountancy isn’t even the most important effect of creating a basic setup.

  • The activation energy for getting to an alpha version of a project goes down even further, so you’ll start more stuff
  • Your projects, even the ones you don’t immediately feel very invested in, will look good and be functional even quicker, so you’ll finish more stuff
  • You won’t be tempted to hack together any crappy solutions to save yourself the pain of doing things right but tediously, so your stuff will suck less
  • And you won’t have to keep pausing your creative, expansive coding to install the gem or set up the architecture that you take for granted in your day job, so will get much more uninterrupted experimentation time at the start of your project, when you need it most

All it needs is for you to be slightly more methodical the next time you start a new project, and get all the generic stuff out of the way before doing anything fun. Then push to Github and clone it the next time you want to mess around with something new. If you find a new must-have gem or pattern then just add it to your basic Rails repo. Your instant and infinite supply of free Ferraris just became an instant and infinite supply of free custom Ferraris. Do you have enough money to pass on custom Ferraris?

(Feel free to fork mine (https://github.com/robert/basic-rails) , but I suggest that you don’t. We might have very different ideas of what qualifies as indispensable.)

Subscribe to my new work on programming, security, and a few other topics. Published a few times a month.
Follow me on Twitter ➜ RSS ➜