I read a great post by Graeme Mathieson that walks through how he sets up a new Rails 4.2 project from scratch. At the bottom of the post he mentions it takes him half an hour or so. I’ve been meaning to play with Rails Application Templates and figured this would be a good opportunity to see what they can do and if they can cut down this boilerplate time.
The repo containing the version of my code at the time of writing is at chrismcg/rails_templates. The main difference is that I start with Puma instead of Unicorn so the server is threaded. I also added in Pry because I love it and Dotenv because it’s so handy.
Before starting I’d a quick look round for some of the old template solutions I remember from a few years back and to check for anything new. I came across this excellent summary from the RailsApps people. After reading it I decided to stick with what Rails provides rather than add another dependency with more flexibility than I need.
The first step is setting up the defaults you want when you run
These are put in
~/.railsrc. Mine looks like:
-d postgresql --skip-test-unit --skip-bundle
I’m setting the default database for new apps to PostgreSQL, skipping test unit as the template installs RSpec, and skipping bundler as the template runs that when it’s needed.
One of the things I liked about Graeme’s post is how he makes logical commits after each step. It’s easy to control git from inside a template so I decided I’d follow his lead as it makes it easier to debug each step when necessary. It also allows for reverting steps that don’t make sense for whatever app I might be building.
It’s a bit slower doing it this was as you have to run bundler multiple times but I’m personally happy to take that hit to have sensible history.
I’m not going to go through the blog post section by section showing how I automated each step. If you open up Graeme’s post and my template side by side it should be pretty obvious.
What I really liked when I’d finished was:
- Having testing and a default homepage setup and ready to go.
- Having guard ready to go in a different terminal.
- How fast it finished when the gems were already installed.
Some problems I ran into on the way were:
- Figuring out the correct
sedinvocation to make the edits to the files. The template will most likely only work as is on OS X.
- Puma doesn’t like having
port ...in the
config/puma.rb, this made it complain about the port already being bound.
- Spring would get started and then I’d remove the directory while it was running… This made it very confused and it hung a few times while I was in the middle of developing the template.
The main drawback I see is that the template is a big long script with no error handling. I’m not actually that bothered by that as it’s easy enough to tweak Chances are I’ll spend less time fixing anything that comes up than over-engineering now it to try and make it never fail.
There are no dependencies other than
rails. I only have to worry
about having the right version of Rails in my gems and I’m good to go. It’ll
be easy to copy and tweak if I find I need a version that includes Redis or
some of the Postgres extensions.
So all of this was to save some time starting out on a new app. How did I do?
Well, with a gemset just containing Rails 4.2 gems it takes a bit over 2 minutes.
rails new skeleton --template=~/dev/rails_templates/default.rb 31.34s user 5.46s system 28% cpu 2:09.38 total
Re-running the command you can see that most of that time is downloading and installing gems so there’s definitely a win here.
rails new skeleton --template=~/dev/rails_templates/default.rb 8.94s user 1.35s system 63% cpu 16.105 total
I’m pretty happy with this. It allows me to quickly setup a scratch Rails app to try something out. (A tip I got from the sample chapter of Justin Weiss’ Practicing Rails book.)
Using a template and gems I’ll already have installed means these scratch apps are going to be very quick to setup and close to how the main app I’m working on is configured. Anything I learn can easily be brought across to the main app and of course when I do want to start a real app I know I’ll be good to go.