Search code examples
ruby-on-railsrubyrubygemsrvmcapistrano

Relation RubyGems, Ruby Version, Bundler Version, RVM and Capistrano Conflict


I have an ancient Ruby on Rails project that uses a Capistrano installation process. It currently runs Ruby 2.5.1 and Rails 5.2. I have been working on an updated version and while doing so probably have messed up the old installation. Right now I need to repair the Capistrano deployment process to install a fix before migrating to the new situation.

I use rvm to manage the different Ruby versions.

On my local machine, the app runs fine using ruby 2.5.1, gem 3.2.3, bundle 1.17.3. This is also the bundle version stated in Gemfile.lock.

On the server, there is ruby 2.5.1, gem 2.7.6 and bundle 1.16.1. (rvm is also installed.) When deploying, I get the error message rubygems.rb:289:in 'find_spec_for_exe': can't find gem bundler (>= 0.a) with executable bundle (Gem::GemNotFoundException). In fact, running gem list bundle in the current directory (the version of the software that is still running) tells me that the current version of bundle is 1.16.1. However, the Gemfile.lock of the currently running version of the software states it was bundled with 1.17.3.

I think I should probably install bundle 1.17.3 on the server as it really does not seem to be installed (in /home/deploy/.rvm/gems/ruby-2.5.1/gems/). However, I think that before I start installing things on a running production server I should be clear about what I am doing, hence my questions.

  • How is the gem (RubyGem) version connected to the Ruby version? The versions listed on my machine and on the server seem to suggest that the RubyGems version should match the Ruby version. Is that true?
  • How is the version of gem (RubyGems) determined? (My guess: rvm does it, but how?) I am particularly interested in how the version 2.7.6 got onto the server since Ruby 2.7.6 is not installed.
  • How are the versions of RubyGems different? I haven't been able to find anything on that point. Sometimes the internet is a nightmare to search.
  • Why does Capistrano not install the bundler version mentioned in the Gemfile.lock? Does it install gem (RubyGems), and if so, how does it know which version to install?
  • How was I able to deploy successfully last time, when the Gemfile.lock already had the information "BUNDLED WITH 1.17.3" in spite of there being no bundle 1.17.3 installed on the server, and why does this break installation now?

And finally, more because I always get confused:

  • Why is it called "bundler" and "RubyGems", but the programs I run are called "bundle" and "gem"? The only statement I could find about that is that "bundle" is the CLI tool for "bundler", but what else is there to "bundler" apart from the CLI tool?

Solution

  • What is RubyGems?

    RubyGems is a LIBRARY (a bunch of Ruby code) that comes installed with Ruby. This library allows you to install gems (gem install something), and it also allows you to load those gems from your programs (require 'some_gem'). So in summary it is a bunch of code that allows you to make use of gems and everything that comes with the gem ecosystem (installation, management, usage).

    Physically you can find the RubyGems code here:
    https://github.com/rubygems/rubygems

    You can read the description of that repository.

    What are the gem and bundle commands, and how are they related to RubyGems and Bundler?

    gem is just the command which allows you as a human to interface with the RubyGems library code, that I just referenced above.

    It is not more nor less complex than that. When you run the gem command, it will load the RubyGems library code from the Ruby installation (which I just showed you where to find the code on GitHub). Then the gem command calls the appropriate methods in this library, in order to fulfill your request (remove a gem, install a gem, query information about a gem, and so forth).

    Bundler and the bundle command are no different. Bundler is also a library of code, and bundle is the command to interface with this code, but instead of installing and managing gems system-wide, like RubyGems allows you to do, Bundler allows you to manage and install gems on just a project basis. So think of Bundler as kind of a project-isolated gem manager. This as opposed to RubyGems, which is a system-wide gem manager.