Each Ruby version has a default set of gems which are included when installing a specific version of Ruby. In practice, these default gems are infrequently updated but knowing how to resolve updates can save you time and keep your work humming along unhindered. This article will take a closer look at your default gems, how to manage them, and how to upgrade them with confidence. 🚀
In case you need a quick solution for updating a default gem, here are the steps using the Etc gem as an example:
# Ensure the latest version of the default gem is installed. gem update etc --default # Launch IRB, copy the default specifications directory path to clipboard, and exit IRB. irb Gem.default_specifications_dir exit # Move the default gem specification into the global/normal specifications. mv <default_specifications_path>/etc-1.3.0.gemspec <default_specifications_path>/.. # Double check the new version of the default gem is the version you expect: gem list etc # You should see the following output where Version 1.4.0 is now the default version: # etc (default: 1.4.2, 1.3.0)
That’s it…although it would be a good idea to reload your shell or — better — relaunch your terminal to ensure the above changes are fully loaded in your current environment.
The rest of this article will explain the above steps in greater detail.
Now that you have a rough idea of default gems, where they are located, and how to manage them, we can take a closer at how all of this works. For example — as mentioned earlier — I sometimes run into this issue when upgrading my machine during weekly maintenance or at end of the year when there is a flurry of activity by the Ruby Core Team due to updating default gems in preparation for a new Ruby version release on Christmas Day.
⚠️ Both RubyGems and Bundler (although I forget where they specifically mention this) recommend not tampering with default gems if you don’t have to because modifying default gems might cause unexpected behavior with your Ruby code. This is wise advice so only do this if you have a strong understanding of how RubyGems, Bundler, and how your own dependencies work.
Ideally — when upgrading a default gem — you should only need to run the following (again, using the Etc gem as an example):
gem update etc --default
Another way would be to specify the version:
gem install etc --default --version 1.4.2
The problem with either of the above is that RubyGems will mark both the old and new version as default versions. Also — once a gem has been marked as default gem — there is no useful way to remove a default gem’s version(s). Even running
gem help uninstall provides no additional information and is why manual intervention is required.
Default Specifications Path
Remembering the current path to your default gem specifications is probably not knowledge you keep in memory (kudos if you can remember this path, though). Thankfully, RubyGems make this easy by executing the following within IRB:
This is especially handy when jumping between versions via your Ruby Version Manager since the path will differ by version. For example, at the time of this writing, my full path is:
Once you know the default gem, version, and root path it becomes trivial to manage the specification by moving it from the
default folder up one level to where all general specifications live:
mv <default_specifications_path>/etc-1.3.0.gemspec <default_specifications_path>/..
💡 Should you find it easier to view your gems specifications via your file browser, then run the following:
# Format: open -a "Finder.app" <default_specifications_path> # Example: open -a "Finder.app" $HOME/.cache/frum/versions/3.1.3/lib/ruby/gems/3.1.0/specifications/default
Once the specific version of your gem is no longer a default gem, you can verify your environment matches your expectations by running:
gem list etc
You should see the following output where Version 1.4.0 is now the default version:
etc (default: 1.4.2, 1.3.0)
You want to verify that only
1.4.2 — as shown above — is the default version while
1.3.0 is the older, no longer default, version. This also means you can safely uninstall the older version if you know you know longer need it by running:
gem uninstall etc --version 1.3.0
Depending on the default gem you are manually modifying, you might need to rebuild native extensions especially if you are keeping the old version around. To resolve, you only need force RubyGems to rebuild the native extensions as follows:
# Format: gem pristine etc --version <version> # Example: gem pristine etc --version 1.3.0
I hope this information has demystified how default gems work so next time you encounter issues (if any) you have a quick way to resolve conflicts and return to work unencumbered. Enjoy!