One of our internal use gems includes some executable scripts which are basically wrappers around other gem executables.

Most of these gems are part of the application’s Gemfile, but sometimes, they are globally installed gems. An example of one such case is Mailcatcher, which, due to the gem’s own dependencies (mainly ActiveSupport), should not be included in a Rails app’s Gemfile.

The problem we ran into is that, when trying to execute the global Mailcatcher from this wrapper script, it would actually try to execute within the Bundler environment, and resulted in this error:

mailcatcher is not part of the bundle. Add it to Gemfile.

The script looked something like this:

#!/usr/bin/env ruby

... some setup stuff ...

exec 'mailcatcher -f -v'

What we needed to do was break out of the Bundler environment with Bundler.with_clean_env. The Bundler documentation describes as such:

Any Ruby code that opens a subshell (like system, backticks, or %x{}) will automatically use the current Bundler environment. If you need to shell out to a Ruby command that is not part of your current bundle, use the with_clean_env method with a block.

Updating our wrapper script as such solved the issue:

#!/usr/bin/env ruby

... some setup stuff ...

Bundler.with_clean_env { exec "mailcatcher -f -v" }