Invoke Rails and Rake Faster! And 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 are dog 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 script/rails and script/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|new" =~ $1 ]]; then
if [ -x script/rails ]; then
script/rails "$@"
else
bundle exec rails "$@"
fi
else
if [ -x script/rake ]; then
script/rake "$@"
else
bundle exec 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, 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 chooses between using script/rails and bundle exec rails. In general, I’ve learned 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.
script/rake
A script/rake file is not included in standard Rails 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
Wrapping up
Pretty straightforward, right? I find that this simple r command is now an indenspensible part of my Rails toolkit. Compared to straight up rails and rake, it’s fewer keystrokes, fewer mistakes, and a bit faster to boot.
Suggestions? Discuss the Gist on GitHub.
comments powered by Disqus