Ruby 3.1 + Rails 7: a summary of changes

share this article
A small ruby gem on the background of coal

It’s an exciting time for Ruby enthusiasts. With the release of Ruby 3.1 as well as Rails 7, we have new toys to play with and test. It’s exciting to find out what has changed, so we compiled a (non-exhaustive) list of some of the biggest new features in both the language and the framework.

Ruby 3.1

Ruby logo

Introduced in late December 2021, this version of Ruby comes with a number of new tricks. Ruby 3’s main themes are speed and performance. The original goal from December 2020 is to make the language three times faster than Ruby 2.x. 

YJIT

Firstly, Ruby already has a JIT compiler, MJIT. Sadly, it isn’t delivering as expected in terms of performance. YJIT, which was originally developed at Shopify, is now more widely available and reportedly more suited to efficiently handling Rails code – by 15 to 19%. YJIT achieves this by using basic block versioning with a JIT compiler inside. It warms up fast, too. As the compiler is still very new, it’s not yet enabled by default.

New debugger

The story of the debugger is similar to the story of the compiler. The old debugger, lib/debug.rb wasn’t up to performance standards. As such, debug.gem was introduced, with the promise of not affecting application performance as it searches for bugs. It also offers remote and multi-thread debugging, as well as a number of other neat features.

Error messages

While we’re on the subject of debugging, the Ruby 3.1 bundle includes the error_highlight gem, which, as the name suggests, offers more effective error messages.

Hash syntax

This addition, particularly useful with keyword arguments, adds the option of omitting the keys of a hash when the keys and a variable method in the scope have the same value. It also works for keyword arguments values for methods. The result should be more concise code.

Pattern matching

Ruby 3.1 allows you to skip the parentheses for single-line pattern matching. Additionally, the ^ operator can now accept an expression.

Block forwarding

Here’s another quality feature. Thanks to anonymous block forwarding, passing a block argument to another method doesn’t require you to name it. All you need to do is refer to it.

Pin operator

This improvement means that the pin operator now comes with support for expressions, constants, as well as instance and class variables.

New method

Class#subclasses returns the directly inherited subclasses of the class in question.

IRB

What’s new with IRB? An autocomplete menu, as well as access to the documentation via tabbing through the options.

Rails 7

Ruby on Rails logo

Released in early January, the 7.0.1 version of Ruby on Rails has been long awaited. Basecamp, Github and Shopify have already had the alpha release on production, which makes for some level of guarantee of the release’s stability. Let’s take a look at what we get from Rails 7, and how we feel about it.

JavaScript

One significant change is that, if you want JavaScript in your Ruby on Rails, you don’t need NodeJS or Webpack. You might expect this to come at the cost of using npm packages, but it doesn’t, they are still available. The new default is to import maps through a gem, and handle dependencies with CLI.

The potential downside is that, without transpiling, a lot depends on browsers supporting ES6 out of the box. And using TypeScript or JSX is also out. But you can handle this by using the appropriate setup for your situation.

Turbo, Stimulus and Hotwire

Instead of the previous package of Turbolinks and UJS, Rails 7 comes with Turbo and Stimulus by default. And on top of that, Hotwire provides fast updates to the DOM. It’s a step away from using a lot of JavaScript in web applications, meant to ensure faster loading, server-side rendering for templates, and a more productive development process.

Database layer encryption

Thanks to Rails 7’s encrypt method, we can now mark specific database fields as encrypted. These attributes are then used as normal, because Rails automatically handles encrypting and decrypting between the database and the app.

Zeitwerk mode

This change is worth paying attention to, as it can affect older applications that use the classic loader. With Rails 7, all apps must switch to Zeitwerk mode – which is easy to do.

Asynchronous queries

With the new load_async method, you can query data and fetch results in the background. So, loading a number of unrelated queries for a controller action will be faster.

Unlimited retry jobs

Just like it says on the lid: using :unlimited as the attempts parameter for retry_on results in no limit on the number of retries.

Association

If you want to find out if an association is present on a record, you can now use where.associated(:association).

Tag attributes

The new tag.attributes method, used in views, translates a hash into HTML attributes.

Controller actions

If you want to start streaming a file that is in the process of being generated, you can simply use send_stream inside a controller action. You’ll get an instant response, telling the user that something is going on under the hood.

ActiveStorage

By naming variants on ActiveStorage, you can avoid specifying their size every time.

Sole

When you’re looking for a single record, you can specify this for your query by calling sole or find_sole_by.

How do we like Ruby 3.1 and Rails 7 so far?

Those Rails experts at United Ideas who got to work with the newest versions of Ruby and RoR are optimistic about the changes made so far. We’re definitely glad that the programming language and framework we love is growing and improving. We’re also pretty excited about some of the new features – we’ll leave the details for future blog posts, in which we’ll dive into our experiences with Ruby 3.1 and Rails 7.

What about you? Are you a fan of the new versions? Or would you like to upgrade your app? Let us know, we’d love to hear from you.

Wanna meet us better?

Come and join us