As has been a yearly tradition, the new 3.0.0 version of Ruby was released this Christmas. Not only did we get a new version but a major version, the first in ~7 years since Ruby 2.0.0 came out!
This holiday release is also my favorite present to receive each year. While I am fully aware playing with a new version of Ruby might be an odd thing to look forward to during the holidays, I enjoy exploring the new features. The following are the results of my exploration thus far.
Before you ramp up learning about Ruby’s new feature set, you might want to take advantage of articles written earlier, including:
Ruby 3.0.0 Release Notes - The official notes from the Ruby Core team.
Ruby 3.0.0 Version Notes - Highly recommend bookmarking or macro’ing this great resource for all of your Ruby version needs. I’ve been using this site for years, via an Alfred macro, for quickly looking up Ruby version related information.
Ruby 3.0.0 Feature List - Provides a high level overview of what’s new in Ruby 3.0.0.
Upgrading from Ruby 2.7.2 to 3.0.0 was fairly straight forward. Even dealing with a major version bump, the endeavor took less than a couple of days.
I’m happy to report that all ~30 projects hosted on this site, including this site itself, are now running on Ruby 3.0.0. 🎉 I noticed a few interesting issues while upgrading, though:
Download - The Ruby 3.0.0 tar file is no longer in a bzip2 format but uses gzip now instead. This tripped me up, initially, as I’ve configured my continuous integration builds to automatically install the latest version of Ruby based off of the
.ruby-versionof each project so I had CI build failures until I noticed the format had changed.
Keyword Arguments - Prior versions to 3.0.0 have warned about the use of keyword arguments so had done the work to upgrade all projects to explicitly define positional and keyword arguments. Despite the pre-planning, there were a few surprises:
If you are passing a
Hashthrough several methods, ensure you are explicit in splatting the hash out in all messaging (i.e.
**arguments). For more, see the official documentation on positional and keyword arguments.
If you are metaprogramming, and use a combination of positional and keyword arguments you’ll need to explicitly splat the positional and keyword arguments too. Example:
def method_missing *positionals, **keywords, &block.
Frozen Regular Expressions and Ranges - These are frozen by default now, so you can happily avoid adding
#freezeto object definitions. I still wish strings would have been frozen in 3.0.0 but that decision was vetoed a couple years ago. We’ll have to continue using the
# frozen_string_literal: truepragma in the meantime. By the way, you can use the Pragmater gem to manage frozen strings as well as other pragmas if you like.
Endless Methods - In order to define endless methods, you are now forced to use parentheses which is a major bummer. I’ve always loved that parentheses can be avoided, for the most part, in Ruby. Still, being able to collapse several lines of code is handy. If using Rubocop, you might need to wait for a fix because endless methods will cause
Pattern Matching - I’ve been using pattern matching in several projects so was happy to remove use of
Warning[:experimental] = falsefrom source code that would effect downstream users.
Refinements - I’ve been maintaining the Refinements gem for several years now, supporting
Hash#transform_keys(also known as
Hash#rekey). I was happy to delete code I no longer have to maintain.
Syndication - The RSS gem, used to power the syndication of this site, is no longer packaged with Ruby and is now a separate install. For more on this, here is the full list of Ruby 3.0.0 Default and Bundled gems.
There is still much to learn and use within Ruby 3.0.0. In particular, I’ll be spending a bunch of time with the following:
Happy holidays! I’m looking forward to a better year ahead, with Ruby 3.0.0 leading the way. 🚀