Nikolay Sturm's Blog

Musings about Development and Operations

A Terminal Setup for Complicated Development Environments

| Comments

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.

Automating startup

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 start.

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. cms
1
2
#!/bin/bash
roxterm -T cms -e mux-cms
  • mux-cms then starts tmuxinator
1
2
#!/home/sturm/.rvm/bin/rvm-shell
mux start cms

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 sleep 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.

coding tab example

Conclusion

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!

Comments