While attempting to upgrade our local bundler version to 1.9.6, we ran across a few issues that others may also experience when dealing with a mature Ruby/Rails application. As of version 1.9.0, bundler upgraded their internal dependency resolver to use Molinillo, the same dependency resolver used by the Cocoapods dependency manager for Swift and Objective-C. This change may yield unusual errors when running bundle install
:
Resolving dependencies...........................
Your Gemfile requires gems that depend on each other, creating an infinite loop.
Please remove gem 'XXX' and try again.
Or:
Resolving dependencies....
Bundler could not find compatible versions for gem "mini_magick":
In Gemfile:
some_gem (>= 0) ruby depends on
another_gem (~> 1.0.0) ruby depends on
mini_magick (~> 3.6.0) ruby
Gross. What’s the problem?
A matter of source
Most Gemfiles probably contain just one source
line at the top of the file (for example: source "https://rubygems.org"
), that tells Bundler where to go to look for gems defined in the Gemfile. If all the gems come from a single source, no problems will come up, but we at Lumosity have multiple sources defined. Not only do we have rubygems.org as a source, but we also have private gem repos as well. Bundler will warn of these multiple sources:
$ bundle install
Warning: this Gemfile contains multiple primary sources. Using `source` more than
once without a block is a security risk, and may result in installing unexpected gems.
To resolve this warning, use a block to indicate which gems should come from the
secondary source.
To upgrade this warning to an error, run `bundle config disable_multisource true`.
So what’s the best thing to do? Start using source blocks, as defined in the bundler manual.
Here is a simplified example of our Gemfile without source blocks:
1
2
3
4
5
6
7
8
source 'https://rubygems.org'
source 'http://rails-assets.org'
source 'https://private-gem-repo-example.org'
gem 'jquery-rails'
gem 'rails'
gem 'rails-assets-underscore'
gem 'some_gem'
And now with source blocks:
1
2
3
4
5
6
7
8
9
10
11
12
source 'https://rubygems.org'
source 'http://rails-assets.org' do
gem 'rails-assets-underscore'
end
source 'https://private-gem-repo-example.org' do
gem 'some_gem'
end
gem 'jquery-rails'
gem 'rails'
With the addition of source blocks in our Gemfile, bundler can find gems in their respective repositories, and resolve their dependencies with ease.
Note: We kept source ‘https://rubygems.org’ at the top of the Gemfile to serve as the default gem repo for Bundler. There is no need to use source blocks when it’s the default/highest priority source.