How and Why to Upgrade the Ruby Version in Your Project
A common question I get from Ruby on Mac customers is, “how do I install older Ruby versions, like 2.6.x and 2.7.x?”, where the “x” is older than the latest supported version. They typically ask this because they’re trying to run an existing project (such as a Rails app, Jekyll site, React Native app, or other Ruby project) which specifies an old Ruby version.
For example, if the
.ruby-version file is set to Ruby 2.7.0, they try to install 2.7.0 on an Apple Silicon Mac, but they get a compilation error like this:
linking shared-object zlib.bundle make: *** [build-ext] Error 2 !!! Compiling ruby 2.7.0 failed!
And then they waste time looking up that error message or trying to find other ways to install 2.7.0.
It’s understandable that people who are new to Ruby might think that the Ruby version specified by the project is the only version they can use to run the project. Or perhaps they know there’s a newer version they can use, but don’t know how to update the project.
If you’ve been wondering the same thing, I’ll show you step by step how to update the Ruby version in your project. But first, let’s go over why and when you need to upgrade.
Why upgrade the Ruby version in your project?
Every year on December 25, a new version of Ruby gets released with new features and performance improvements. This is when the first or second digit in the version number changes. For example: 2.6, 2.7, 3.0, 3.1, 3.2. In between these main versions, the only changes that get released are bug and security fixes. This is when the third digit changes. For example: 2.7.1, 2.7.2, all the way up to 2.7.7.
When a security issue or bug is discovered and fixed, the fix gets applied to all main versions that are currently supported. Just like new main versions are released every year on December 25, old versions reach end of life (EOL) on March 31, three years and three months after their initial release. endoflife.date is a great site for visualizing the support status of a bunch of languages and tools.
For example, if a security fix was released in January 2023, it would be available in 3.2.1, 3.1.4, 3.0.6, and 2.7.8. However, if another one was fixed in April 2023, it would only be available in 3.2.2, 3.1.5, and 3.0.7 because Ruby 2.7.x reaches EOL on March 31, 2023.
This means that if your Ruby project is using a version that has reached EOL, or if the third digit is smaller than the latest version, then your project potentially has a backdoor for malicious people to exploit.
When is a good time to update the Ruby version in your project?
Given what we learned above, there are two situations where updating is a great idea:
- Whenever a new security/bug fix is released
- When your project’s Ruby version will reach EOL soon, or has already
Patch releases within a version only contain security and bug fixes, which means they won’t break your project’s code, so it’s perfectly safe to update to the latest release. In the seventeen years I’ve been using Ruby, I don’t remember ever having an issue updating the third digit of a Ruby version.
Even updating the second digit has mostly been painless, such as going from 2.5.x to 2.6.x, or 2.6.x to 2.7.x. The two times to expect breaking changes is when the first digit changes, such as going from 2.x to 3.x, or right after the second digit has changed.
For example, Ruby 3.2.0 was released on December 25, 2022, but you couldn’t generate a new Rails app with it on that day because Nokogiri, one of the gems that Rails depends on, didn’t support Ruby 3.2.0 yet. Nokogiri didn’t add support for Ruby 3.2 until January 12, 2023.
So, if the project you’re trying to run is currently set to 2.7.0, for example, then the first thing you want to do is update it to 2.7.7, which is the latest release in the 2.7.x series as of today. It makes little sense to use a version less than the latest one in a series. You can see the current latest versions on endoflife.date.
Then, once your project is running on 2.7.7, I recommend starting to plan the upgrade to 3.1.3 because 2.7.x will reach EOL at the end of March. It will also likely take more time to upgrade due to the breaking changes.
The only time I can think of when you might not be able to update to a new release is if the service you use to deploy your project doesn’t yet support the latest release. Most well-known services, like Heroku, are quick to add support for releases shortly after they come out. If the service you use is slow at updating, I recommend letting them know that having access to security fixes in a timely manner is important to you, or switch to a better service.
How to upgrade the Ruby version in your project
Now that you understand why it’s important to use the latest releases, I’ll show you step by step how to upgrade your project.
- First, you need to have a proper Ruby development environment with a version manager, such as asdf, chruby, frum, rbenv, or rvm. If you’re a Ruby on Mac customer, you’re all set with that part.
Decide which version you want to upgrade to. This should be either 2.6.10, 2.7.7, 3.0.5, 3.1.3, or 3.2.0. Note that because 3.2.0 was released less than a month ago, it might not yet be compatible with your project.
Then check to see if it’s not already installed. The command you’ll use to check will depend on the version manager you’re using. If you’re a Ruby on Mac customer, you can list all installed versions with
If it’s not already installed, install the version you want to upgrade to. The command you’ll use to install the desired Ruby version will depend on the version manager you’re using. If you’re a Ruby on Mac Prime customer, you’ll run
ruby-installfollowed by the version number. For example:
If you have Ruby on Mac Ultimate, you’ll use the
romCLI, which installs Ruby almost three times faster than Prime, and faster than any other Ruby version manager. It also automatically uses the best configuration settings for that version. Stay tuned for a comprehensive comparison of all the major version managers, coming soon to this blog.
rom install ruby 2.7.7
If you need to install 2.6.10, you’ll either need to use Ruby on Mac Ultimate, or try one of the solutions in my article about installing Ruby 2.6.10 on macOS.
- Quit and restart your terminal app.
cdinto your project directory
If you track changes with Git, create a new branch:
git checkout -b upgrade-ruby
- Open your project in your favorite editor, and find all files that specify the current Ruby version. This will usually be in
Gemfile, and possibly other files if you run tests in a CI service like CircleCI or Travis, or if you have a Docker setup.
- Replace the current Ruby version with the one you want to upgrade to in all of the necessary files, except
Gemfile.lockbecause it should never be edited manually (unless there are merge conflicts, but that’s a topic for another time).
- If you had to replace the Ruby version in both
.ruby-versionand in the
Gemfile, you can save a step in the future by updating your Gemfile so that it reads the Ruby version from
cdout of your project (for example, by going to your Home folder with
cd ~), and back into your project with
cd -(a shortcut for going back to the previous directory). This is needed for your version manager to pick up the new Ruby version.
- Verify that you are indeed using the new version by checking the current active Ruby version:
ruby -v. If not, then switch to it manually. If you’re a Ruby on Mac customer, you would run
chrubyfollowed by the version number.
- Install bundler:
gem install bundler
- If you get any errors during
bundle install, you might need to update the gems that are causing the errors. You might also need to update the Bundler version in your project:
bundle update --bundler
- Run your tests and make sure your project still works.
- Once everything looks good, commit the changes in Git if you’re using it, then merge your branch to your
masterbranch. If you’re on a team, open a pull request and explain the importance of updating your project’s Ruby version.
I hope this helps! If you prefer personalized help, you can buy Ruby on Mac Ultimate, which comes with a 30-minute consultation, worth $150 on its own.