When Rails applications grow, they accumulate more and more dependencies. This not only increases load time, when you integrate additional services like elasticsearch, it becomes ever more complicated to get a local server or test suite running.
When reviewing diffs and running the test suite, I often forgot to start a service and had to rerun the suite after failing half way through. So I finally sat down and configured some tools to ease my developer life.
My base setup
I prefer developing with vim on the command line and use a single full-screen terminal running tmux. Before, I started a rails server on tab 0, ran vim in tab 1 and added tabs dynamically as needed.
Enter the search
When we added a local search engine to one of our Rails applications, life became complicated. Suddenly I had to remember starting the search server before testing the application. As I only worked on it every now and then, I often forgot to start the search service, but still I coped.
When we added a local search engine to another of our Rails applications, life
became tedious and I had to change something. The solution was to introduce
foreman. It lets you define all the
services you need in a
Procfile, so you only have to run a single command
foreman start and everything is up and running.
The new setup was
foreman start in tab 0 and vim in tab 1.
I still had to remember starting foreman manually, so the next step was to
automate that. For this task I chose
tmuxinator which allows you to start
pre-configured tmux sessions with a single command. I settled with starting
foreman, a rails console and a shell, running
git fetch origin, which I would
later use for starting vim. The neat thing about running git instead of
starting vim directly is, that I get an idea about recent changes right at the
I said earlier, that my terminal already uses tmux as a shell, so I needed a way to circumvent this default behaviour and start tmuxinator instead. This isn’t much of a problem, if tmuxinator is installed somewhere in your $PATH. Using rvm, however, tmuxinator is only available after rvm initialization. To handle this, I settled on this workaround:
- start a shell script from the window manager named after the project, e.g.
mux-cmsthen starts tmuxinator
Adding bells and whistles
One thing that had bothered me for a long time, that I finally decided to attack as well, was the slow rails load time. For one of our applications, it takes about 20s to load all the gems. I had previous experience with spork to speed up test load times, but I also wanted to speed up rake and service start-up times. So I decided to give zeus a try.
Zeus’ big advantage over spork is, that you don’t have to change anything in
your application, but instead commands are zeusified. Instead of
rails console, you run
zeus console. Zeus works only with Rails 3
applications running on Ruby 1.9.3. Lucky for me, we upgraded our last
application to Ruby 1.9.3 a few weeks earlier.
Another requirement stated on zeus’ website is a GC-patched Ruby. So far, I haven’t needed it at all. Plain Ruby 1.9.3 works fine for me.
What doesn’t work perfectly, yet, is orchestrated startup with zeus. The zeus
server obviously takes quite long to start and won’t be accessible for clients
during that time. The only answer I came up with so far, was adding
to process startups in my tmuxinator config.
After reducing startup times considerably, it finally made sense to integrate guard and guard-rspec. I run these split pane on the third tab with my editor, having one source/spec combination open per vim tab.
The command line is a powerful base and there are many tools to improve a developer’s life. Can you think of further improvements? Let us know in the comments!