As Ruby applications grow, the number of external libraries these applications use can grow at the same rate–if not faster, in some cases. This growth can pose problems when gems install their dependencies. If two gems rely upon different versions of the same library, then installing both gems runs the risk of creating an error scenario due to gem incompatibilities. Bundler, a Ruby gem, provides you with an easy way to manage these gem and avoid conflicts, allowing you to focus on your application’s code instead of troubleshooting issues with support libraries.
- Ruby version – 2.2.1 or newer
Note: this article uses vim for text editing. Replace “vim” with your editor of choice if you prefer to use a different text editing tool. (And if you accidentally find yourself stuck in vim, here are some tips to help you get unstuck.)
Managing Complex Interdependencies
As your application grows in complexity, you may see version conflicts in your application’s gemset. These conflicts may prevent your application from functioning correctly as the number of gems you use–and the number of gem interdependencies–grows. You might consider using RVM in a more restrictive fashion, but this solution only gives you the opportunity to control the current Ruby version and associated gemset–it does not handle gem dependency issues, which can occur among different gem versions using the same base version of the Ruby language. Going through the dependencies of all gems to find these conflicts and download compatible gem versions is a long and tedious process. Luckily, we can use the Bundler gem to manage our gemsets and take the guesswork out of using shared libraries.
Installing Bundler to Manage Gems
To get started with Bundler, we first need to install the gem:
gem install bundler
Note, some versions of Ruby may use the form
gem2.2 install bundler.
This command installs Bundler into the current Ruby execution environment. Next, you need to create a Gemfile to manage your application’s gems. Add a new file in your application’s root directory and open it for editing:
Note: Bundler, by default, looks for the filename
Gemfile, capitalized exactly as shown. It will fail, for example, if you instead named your file
You can add your gems at this point, or leave the file empty if you have no external gem dependencies. Bundler uses this Gemfile when downloading and installing gems for your application.
Anatomy of a Gemfile
A Gemfile gives you many different ways to manage your application’s gem sets. You can, for example, specify a new gem source in your Gemfile, which will be searched when running the install:
You can easily add new gem dependencies by putting them on individual lines, preceded by the word
gem. For example, the following line specifies
nokogiri as a gem dependency for your application:
You can also specify specific gem versions by using the familiar RubyGems syntax. The following line adds the Rails gem, but restricts it to Rails version 3.0.0.beta3:
gem 'rails', '3.0.0.beta3'
You can also specify gem groups that only run in specific environments. For example, the following block installs
factory_girl when the Rails environment is either
group :test, :development do gem 'rspec' gem 'guard' gem 'factory_girl' end
These examples are only a beginning. There are a number of other useful features of a Gemfile at bundler.io.
Installing All Gems With Bundler
Once you’ve populated your Gemfile with gems to install, you can install all of your current environment’s gems with the following command:
This command parses your Gemfile and tracks down all of the indicated gems from the sources available both on your system and in the Gemfile itself. It examines all gems for shared dependencies, and then generates a new file (
Gemfile.lock) that contains all of the compatible gems and their versions. Finally, it moves through the created
Gemfile.lock file, installing each relevant gem. Upon completion, your application’s gems will be available to use in your application code.
Other Useful Bundler Commands
Aside from taking all of the headaches out of managing gems with shared dependencies, Bundler also gives you several other tools with which you can manage your application’s gem set. Below are a few example commands that you may find useful during development:
To update all gems in the Gemfile to the latest compatible version:
In production environments, instead of dynamically resolving gems from all available sources, you might want to install just the gems specified in Gemfile.lock.
bundle install --deployment
To run a command within the context of an application’s Gemfile:
bundle exec XXXX
Without the addition of
bundle exec, the command XXXX would run in the system Ruby context, which may contain incompatible gems.
You can review other available commands, and their intended uses, here.
A common problem among programming languages is the concept of “dependency hell,” which arises when two or more third-party libraries rely upon different versions of the same shared library. Bundler gives Ruby developers an easy-to-use tool for both installing and managing complex gem sets. It helps to resolve all of the dependency issues and provides you with a compatibility record for all of your application’s dependencies. Through the use of Bundler, you can quickly resolve conflicts in your consumed gems, and get back to working on the meat of your application code.
Atlantic.net offers managed hosting services which include a layer of business-essential managed services to your hosting packages. Contact us today for more information.