Automatically run 'bundle install' when Bundler can't find a gem

Automatically run 'bundle install' when Bundler can't find a gem
Photo by Michael Dziedzic / Unsplash

Every Rails developer has probably seen the following error:

Could not find <gem> in any of the sources
Run `bundle install` to install missing gems.

This happens if you or someone else adds a gem to your Gemfile, or if a gem version is updated in Gemfile.lock,
and you forget to run bundle install before running a Rails command.

Here's a simple function that handles this automatically, called bundle_install_wrapper(). It first tries to execute the command you pass to it.
However, if Bundler exits with status code 7 (GemNotFound), then it will run bundle install. Finally, it retries the original command.

bundle_install_wrapper() {
  # Run command
  eval "$@"
  if [ $? = 7 ]; then
    # If command crashes, try a bundle install
    echo -e "\033[1;31m'$@' failed with exit code 7."
    echo "This probably means that your system is missing gems defined in your Gemfile."
    echo -e "Executing 'bundle install'...\033[0m"
    
    bundle install # If bundle install was successful, try running command again.
    if [ $? = 0 ]; then
      echo "'bundle install' was successful. Retrying '$@'..."
      eval "$@"
    fi
  fi
}

Usage

Drop the function in your ~/.bashrc, and add aliases for rails commands:

alias rs="bundle_install_wrapper rails server"
alias rc="bundle_install_wrapper rails console"

# etc.

If you want aliases that support any Rails application, you can use something like this:

# Run Rails commands on any version

rails_cmd(){

# Rails 3

if [ -e ./script/rails ]; then bundle_install_wrapper rails3_with_editor $@

# Rails <= 2

elif [ -e ./script/$1 ]; then bundle_install_wrapper ./script/$@

# Rails 4

elif [ -e ./config.ru ] && grep -q Rails config.ru; then bundle_install_wrapper rails $@
else echo "== I don't think this is a Rails application!"
fi
}
alias rs="rails_cmd server"
alias rsd="rails_cmd server -u"
alias rc="rails_cmd console"
alias rg="rails_cmd generate"

See the Ruby on Rails section in my .bashrc if you're interested in more aliases,
and please leave a comment if you have any tips to share.