Lesson Wednesday

Note: Do not run any brew commands on Epicodus computers. Most versioning issues in Ruby/Rails projects are local to the project, not global to the machine. The information below will ensure that your local project environment doesn't conflict with your global environment. If you think that there is an incorrect version of Ruby, Rails, or another tool on an Epicodus machine, please put in a ticket.

In this lesson, we will address a common error that many students run into, both on their personal machines and occasionally the machines at Epicodus.

These issues tend to come up with rails, rake and rspec commands. If you are having an issue with one of these commands, this should always be your first troubleshooting step!

The Issue: Gem Incompatibility


This is a common error when running a rake or rspec command:

$ rake
rake aborted!
Gem::LoadError: You have already activated rake 10.4.2, but your Gemfile requires rake 10.4.0. Prepending `bundle exec` to your command may solve this.

As the error message suggests, this is usually resolved by including $ bundle exec before the rake command. Let's address what this error is, why it occurs, and why bundle exec resolves it.

The Reason: Differing Gem Requirements


The error above generally occurs when one version of an executable script run in the command line (such as rake or rspec) is installed for a project but a different version of the same tool is installed system-wide on the machine. In other words, there is a conflict between the local project's environment and the global environment of the computer you are using.

The error message above reads "You have already activated rake 10.4.2, but your Gemfile requires rake 10.4.0". This means version 10.4.2 of the rake gem has been installed system-wide but the specific project requires version 10.4.0 in its Gemfile.

The Solution: bundle exec


We don't want to remove the incompatible system-wide gem to solve this issue. If other projects or tools require that version, we'll only encounter more errors in other projects.

Additionally, we can't guarantee that simply updating our project to use the newest version will work, either. Other gem versions in our project may not be compatible with this new version. Updating a gem in a large project can result in potential headaches.

Instead, we can prepend bundle exec to our executable script commands. This ensures the executable script uses gem versions from that project's Gemfile, not other versions installed system-wide on the machine.

If we receive an error like the one shown above, we could prepend bundle exec onto the command like this:

$ bundle exec rake:db migrate

This would ensure that we're using the rake versions specified in the project's Gemfile.

bundle vs bundle exec


The bundle command retrieves all necessary gems in a project's Gemfile for use with an application. If a project includes a required Gem that isn't available locally, the bundler reaches out to rubygems.org and retrieves it.

Conversely, as detailed in its Bundler documentation entry, the bundle exec command allows us to run an executable script in the specific context of the project's bundle.

It's important to understand that bundle exec is not a replacement for the bundle command we run after adding gems to our Gemfiles. As we saw in the example above, it's a prefix to prepend onto executable script commands like rake or rspec.

Other Uses


Developers usually don't update large codebases every single time a new version of a tool is released. Updating a huge project to use the latest version of a gem or library often isn't worth it, especially if the older version still works.

It's likely that you'll eventually find yourself working on codebases that don't use the most recent releases of gems, perhaps even while concurrently developing other projects that do. In these instances, bundle exec allows us to effortlessly switch between different projects with different gem requirements, ensuring each has access to the version it requires.

Additional Information


For more details, including a few optional tips and shortcuts check out the But I don't want to bundle exec!_ blog post from the Portland company Thoughtbot.

Additionally, information on this Bundler command and more can always be found in the Bundler documentation

Many Ruby developers always prepend bundle exec to their commands to ensure there's not a conflict between the local and global environment. While it's a little bit of extra work to type, it can save you a lot of trouble down the road.

Lesson 30 of 34
Last updated July 14, 2022