loading...

Completely Remove Ruby 2.7's Default Bundler

st0012 profile image Stan Lo 惻2 min read

Ruby 2.7 comes with the default bundler gem, which always has 2.0+ version. This is a great default in general, especially to the beginners. But in some cases, like when using Rails 4, we want to keep the bundler version under 2.0 to avoid conflicts.

Bundler could not find compatible versions for gem "bundler":
  In Gemfile:
    rails (~> 4.2) was resolved to 4.2.11.3, which depends on
      bundler (< 2.0, >= 1.3.0)
  Current Bundler version:
    bundler (2.1.4)

However, it's not easy to rollback to a older version of bundler. Since the 2.0+ version will be installed as a default gem, simply uninstall it won't work:

$ gem uninstall bundler
=> Gem bundler-2.1.4 cannot be uninstalled because it is a default gem

And these tricks won't work either (at least they didn't work for me):

$ bundle -v
Bundler version 2.1.4

$ gem install bundler:1.17.3 --default
Successfully installed bundler-1.17.3 as a default gem
Done installing documentation for bundler after 0 seconds
1 gem installed

$ bundle -v
Bundler version 2.1.4

$ bundle config default 1.17.3
$ bundle -v
Bundler version 2.1.4

From all the references I can find, the only way to remove it is to delete the bundler-2.1.4.gemspec file from the gem path. The following commands did the trick for me:

$ gem env gempath
/Users/st0012/.gem/ruby/2.7.0:/Users/st0012/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0
$ ls /Users/st0012/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/specifications/**/bundler-*.gemspec
/Users/st0012/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/specifications/default/bundler-2.1.4.gemspec
$ rm /Users/st0012/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/specifications/**/bundler-2.1.4.gemspec
$ gem install bundler:1.17.3 --default
$ bundle -v
Bundler version 1.17.3

But what if we want to perform the same cleanup on CI (like travis-ci) too? Well, I wrote a script for you:

#!/usr/bin/env ruby

gempaths = `gem env gempath`.split(":")
gempaths.each do |gempath|
  # lookup bundler-*.gemspec files and delete them
  # this is the only way to completely cleanup default bundler
  # Note: the bundler gemspecs' paths are different for CRuby and JRuby
  Dir.glob(gempath.strip + "/specifications/**/bundler-*.gemspec").each { |p| File.delete(p) }
end

# Remember to make this file executable

Then you can add this to your CI config file (.travis.yml for example):

before_install:
  - ./cleanup_bundler
  - gem install bundler -v '1.17'

And that's it! I hope this short post can save you from pulling your hair for a few hours šŸ˜‰

If you're a Rubyist and you like this post, please also check the debugging tools I wrote:

GitHub logo st0012 / tapping_device

TappingDevice makes objects tell you what they do, so you don't need to track them yourself.

GitHub logo st0012 / power_trace

Buff exception backtrace with local variables, passed in arguments and instance variables!

Posted on by:

st0012 profile

Stan Lo

@st0012

Senior Software Engineer @ticketsolve. Love Cats, Ruby on Rails and Boxing. Created Goby. Working on tapping_device during weekends.

Discussion

markdown guide
 

--default option of gem command will not install the library files. I think you can use the bundler-1.x with simply gem install bundler -v 1.17.3. After that, The bundler switcher of RubyGems can detect the old version of bundler automatically.

 

Thanks for the comment! But I just tried it with freshly installed Ruby 2.7.1 and it didn't work šŸ¤”

First, I made sure I only have the default bundler 2.1.4. And then I installed version 1.17.3

$ ruby -v
ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-darwin19]

$ gem list bundler
*** LOCAL GEMS ***

bundler (default: 2.1.4)

$ gem install bundler -v 1.17.3                                                                                                                                                                                                              Fetching bundler-1.17.3.gem
Successfully installed bundler-1.17.3
Parsing documentation for bundler-1.17.3
Installing ri documentation for bundler-1.17.3
Done installing documentation for bundler after 2 seconds
1 gem installed

$ gem list bundler

*** LOCAL GEMS ***

bundler (default: 2.1.4, 1.17.3)

But after installing version 1.17.3 it still uses 2.1.4, which can't be uninstalled.

$ bundle -v
Bundler version 2.1.4

$ gem uninstall 2.1.4
Gem '2.1.4' is not installed

$ gem uninstall bundler -v 2.1.4
Gem bundler-2.1.4 cannot be uninstalled because it is a default gem

Now if I create a new Gemfile and run bundle install, it'll still use 2.1.4 instead of 1.17.3.

$ echo "source 'https://rubygems.org'" >> Gemfile

$ bundle
The Gemfile specifies no dependencies
Resolving dependencies...
Bundle complete! 0 Gemfile dependencies, 1 gem now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.

$ cat Gemfile.lock
GEM
  remote: https://rubygems.org/
  specs:

PLATFORMS
  ruby

DEPENDENCIES

BUNDLED WITH
   2.1.4

Did I miss anything?

 

You can use bundler-1.17.3 with bundle __1.17.3__ install. Or After you update 2.1.4 to 1.17.3 on BUNDLED WITH field, You can use bundler-1.17.3 with bundle command.

 

I wrote this script a couple of years ago when working on my Bundler plugin. It's pretty thorough, maybe more than what you need. It also may be a little out of date: github.com/chrismo/bundler-fixture...

 

Please, update your Rails (or whatever) version or don't update the Ruby. That's all, it's simple.

 

Iā€™m maintaining multiple gems, so I need to make sure they are compatible with the latest Ruby release.

 

When a new Ruby release is incompatible with some versions of your gems dependencies ā€” I think it's time to make a new major release. Old gem versions works with old Bundler and Ruby, new ā€” with new, seems legit.