Invoke Rails and Rake Faster!

A handy shell function for running rails and rake commands with fewer mistakes.

As a Ruby on Rails beginner I would always confuse the rails and rake commands. Database migration? rake. Database console? rails. It seemed arbitrary. Later I learned the differences, but still I found myself making fat-finger mistakes between the two. And on top of that, rails and rake can be slow, meaning every mistake can come with a few-second penalty. Finally I got fed up and scripted the following solution in bash.

.bashrc

# Shortcut for `bundle exec rails` and `bundle exec rake`.
# If bin/rails and bin/rake are available, use them instead as they are much
# faster to execute than `bundle exec`.
function r() {
  if [[ "g|generate|c|console|s|server|db|dbconsole|r|runner|new" =~ $1 ]]; then
    if [ -x bin/rails ]; then
      bin/rails "$@"
    elif [ -x script/rails ]; then
      script/rails "$@"
    else
      rails "$@"
    fi
  else
    if [ -x bin/rake ]; then
      bin/rake "$@"
    elif [ -x script/rake ]; then
      script/rake "$@"
    else
      rake "$@"
    fi
  fi
}

What I’ve done in my .bashrc (see my dotfiles) is defined a shell command r that invokes rails or rake depending on the arguments given. If your argument to r is generate, console, server, dbconsole, runner, new, or the one-letter aliases for those, the r command assumes you meant to invoke rails, and does so. Otherwise it assumes you meant rake.

For example:

r db:migrate
==  migrating....
 
r db
Welcome to psql 8.3.17, the PostgreSQL interactive terminal.
r s
=> Booting WEBrick

Short and sweet. No more fat-finger mistakes.

script/rails or bundle exec rails?

You’ll notice that r also favors script/rails over bundle exec rails. You may wonder why; after all we’ve been taught to always use bundle exec to ensure correct behavior of executables in a Rails project. But this is actually overkill for the rails command.

As it turns out, bundle exec rails simply invokes script/rails, which in turn initializes Bundler anyway. So bundle exec rails therefore runs Bundler’s setup twice, and for no good reason. (Actually, Bundler.setup is invoked three times!)

In fact, in my testing script/rails is up to 1 second faster than bundle exec rails. The upshot is that the r command should prefer to use script/rails if possible.

June 10, 2013 update: Rails 4 muddies the waters even further: the rails executable is now in bin/rails. The good news is that r will do the right thing, first trying bin/rails (Rails 4 convention) and then script/rails (Rails 3 convention).

script/rake

A script/rake file is not included in standard Rails 3 projects, but you can use the same trick to get a 1-second boost over bundle exec rake. This may qualify as a hack, so proceed with caution.

#!/usr/bin/env ruby

# script/rake
# Run rake after loading Rails/Bundler; faster than `bundle exec rake`

APP_PATH = File.expand_path('../../config/application',  __FILE__)
require File.expand_path('../../config/boot',  __FILE__)
require 'rake'

Rake.application.run

And don’t forget:

chmod a+x script/rake

June 10, 2013 update: Rails 4 includes a very similar rake script. It is in bin/rake for new Rails 4 projects.

Wrapping up

Pretty straightforward, right? I find that this simple r command is now an indispensable part of my Rails toolkit. Compared to straight up rails and rake, it’s fewer keystrokes, fewer mistakes, and a bit faster to boot.

You just read

A handy shell function for running rails and rake commands with fewer mistakes.

January 2012

Share this post?  Copy link

About the author

Hi! I’m a Ruby and CSS enthusiast, regular open source contributor, software engineer, and occasional blogger writing from the San Francisco Bay Area. Thanks for stopping by! —Matt

GitHub Email LinkedIn