An Overview Of Ruby on Rails 7.1 Features. Part I.• ruby, rails • siaw23
- 01. Rails 7.0.1 released.
- 02. Adding autoload paths to $LOAD_PATH disabled.
- 03. A new #update_attribute! method was added.
- 04. Dart Sass for Rails released.
- 05. A new #stub_const method was added.
- 06. Improved the error message with a missing association.
- 07. ActiveRecord::ConnectionPool is now Fiber-safe.
- 08. Rails 7.0.2 released!
- 09. #to_fs(:format) replaced #to_s(:format).
- 10. Password challenge via has_secure_password added.
- 11. Saving attachments to a record now returns the blob.
- 12. audio_tag & video_tag now accept attachments.
- 13. #destroy_association_async_batch_size added.
- 14. Active Record added a new API for general async queries.
- 15. CSRF tokens can now be stored outside of sessions.
- 16. Keyword arguments for system tests screenshot helper.
- 17. Encrypted attributes on columns with default values.
- 18. Pattern matching for ActiveModel [=Reverted=].
- 19. db_runtime added to Active Job instrumentation.
- 20. Validity check for PostgreSQL indexes added.
- 21. Exclusion constraints are now supported.
- 22. Messageverifier gets a urlsafe: initialization option.
- 23. Order DESC for in_batches.
- 24. db:prepare can load the schema of an empty database.
- 25. Specify the parent class of a job with a job generator.
- 26. datetime_field gets a new include_seconds option.
- 27. Rails added support for Common Table Expressions.
- 28. Pre-defined variants for previews allowed now.
- 29. routes --unused option to detect dormant routes.
- 30. Templates can now define which locals they accept.
Here are links to the other parts of the series:
- An Overview Of Ruby on Rails 7.1 Features. Part II
- An Overview Of Ruby on Rails 7.1 Features. Part III
The Ruby on Rails repository has seen a tremendous amount of activity this year, introducing a wealth of new framework features, fixing numerous bugs and implementing countless performance improvements.
With so much happening in the Ruby on Rails repository, it can be challenging to keep up. However, in this series of blog posts, I will zero in on some of the exciting new features and improvements in the upcoming minor release of Rails, version 7.1.
In this series of blog posts, I will be sharing my favourite new features and improvements from the Rails repository throughout 2022. This is the first of a three-part series, so be sure to stay tuned for the next two instalments of a comprehensive overview of the exciting developments in Rails this year. You can follow me on Twitter where I’ll send updates; if you’re not on Twitter you can subscribe to my newsletter if you scroll to the bottom.
If you want to stay up to date on the latest developments in the Ruby on Rails framework, I recommend subscribing to This Week In Rails for weekly issues.
Please be aware that the code samples were taken out of the various pull requests and docs with some modifications, I haven’t tested them to guarantee they work as they are. That said, all the features described have been merged.
Let’s get started.
01. Rails 7.0.1 released.
Rails kicked off the year with the release of Rails 7.0.1, which introduced support for Ruby 3.1 along with various bug fixes and documentation improvements.
I vividly remember the excitement that surrounded the news of Webpacker’s retirement. Webpacker had been a source of frustration for many developers. The introduction of
./bin/importmap to pin and unpin NPM packages brought back some joy of working with Rails I reckon.
02. Adding autoload paths to
Beginning with Rails 7.1, paths managed by the autoloader will no longer be added to
$LOAD_PATH. This means that they can no longer be loaded using a manual
require call; instead, you can reference the class or module directly. To accomplish this change, the
config.add_autoload_paths_to_load_path configuration option will be set to
false in Rails 7.1 and later versions.
It is recommended to set
false in the
config/application.rb file when running in
:zeitwerk mode. This is because Zeitwerk internally uses absolute paths, and therefore models, controllers, jobs and other files do not need to be in the
require_dependency is not used.
false, you can prevent Ruby from checking these directories when resolving
require calls with relative paths. This can also improve the performance of your application by saving on Bootsnap work and RAM usage as Bootsnap does not need to build an index for these directories.
03. A new
#update_attribute! method was added.
Rails added a new
ActiveRecord::Persistence#update_attribute!method. This method is similar to
update_attribute, but calls
save! instead of
ActiveRecord::ActiveRecordError if an attribute is marked as
04. Dart Sass for Rails released.
Rails released a new dartsass-rails gem that wraps the standalone executable version of the Dart-based Sass for use with Rails 7.
dartsass-rails allows the use of Sass stylesheets with Rails and replaces the previously used Ruby Sass, which has been deprecated. With this gem, Rails developers can take advantage of the latest features and improvements in Sass while working with Rails.
In a new Rails app, you can install Dart Sass for Rails by doing:
The installer will create a default Sass input file,
app/assets/stylesheets/application.scss, where you should import all of your style files to be compiled. When you run
rails dartsass:build, this input file will be used to generate the output CSS file,
app/assets/builds/application.css which you can then include in your app.
05. A new
#stub_const method was added.
#stub_const method was added to easily change the value of a constant for the duration of a block, silencing warnings. The implementation is not thread-safe if you have parallel testing enabled though.
In the example above, by using this method instead of setting
World::List::Import::LARGE_IMPORT_THRESHOLD to 5000, we can prevent warnings from being thrown and ensure that the original value is restored after the test has finished.
Take note, however, that stubbing a constant can have unintended consequences when used in a multithreaded environment. If multiple threads depend on the same constant and each thread attempts to stub the constant, it can lead to conflicting stubs and unpredictable behaviour. To avoid this issue, it is important to carefully consider the impact of stubbing constants in concurrent threads, such as when running separate test suites in parallel.
06. Improved the error message with a missing association.
where.associated with a missing association used to raise a cryptic error message, this has now been improved with a much clearer message. It’s better to show you an example with this one.
Post that doesn’t have an association named
cars, we’d get something like:
Now, we’ll be getting
ActiveRecord::ConnectionPool is now Fiber-safe.
ActiveRecord::ConnectionPool Fiber-safe. Rails has a lot of thread-centric code and does I/O with databases with threads inherently, this pull request makes it possible to switch how the connection pool is interacted with. For instance, if you use a fiber-based job processor or server like
falcon, you should set
:fiber, in which case multiple fibers in the same thread will be used to manage connections.
08. Rails 7.0.2 released!
On February 8, 2022, Rails 7.0.2 was released with a patch that included the reversal of a problematic feature, as well as the introduction of the ability to version the database schema based on the Rails version in use. This new feature allows existing applications to continue using their database schemas generated in Rails 6.1, maintaining the same behaviour and ensuring that the production database schema remains consistent.
#to_s(:format) method was deprecated not long ago in favor of
#to_formatted_s(:format)’s alias was
#to_fs(:format) but this pull request swapped so that
#to_formatted_s(:format) became an alias to
#to_fs(:format). Why? Because
#to_formatted_s(:format) is too long a name for a method that’s used so frequently according to DHH. I concur.
10. Password challenge via
Rails now allows a password challenge to be implemented with the same ease as a password confirmation, re-using the same error handling logic in the view, as well as the controller.
has_secure_password to define a
password_challenge accessor and the appropriate validation. When
password_challenge is set, the validation checks that it matches the currently persisted
For example, in the controller, instead of:
One could write:
I couldn’t describe this pull request in a better way than the author, I grabbed this verbatim from the pull request description. Thanks Jonathan.
11. Saving attachments to a record now returns the blob.
Saving attachments to a record with the
#attach method now returns the blob or array of blobs that were attached to the record. This means we can use blob methods directly on the attachment! If the record fails to save,
#attach will return
video_tag now accept attachments.
Rails extended audio_tag and video_tag to accept Active Storage attachments so instead of:
You can now do:
Rails added a new
ActiveRecord.destroy_association_async_batch_size that allows developers to specify the maximum number of records that will be destroyed in a single background job when using the
dependent: :destroy_async association option. If there are more dependent records than the specified batch size, they will be destroyed in multiple background jobs otherwise they’ll be destroyed in a single background job. This helps to ensure that the destruction of large numbers of records can be handled efficiently without overwhelming the application.
14. Active Record added a new API for general async queries.
In Active Record now, there’s a new API for general async queries. In Rails 7.1 you’ll be able to run aggregate methods as well as all methods returning a single record or anything other than a
find_by_sql asynchronously. So you can do stuff like:
15. CSRF tokens can now be stored outside of sessions.
This pull request allows CSRF tokens to be stored outside of sessions. When sessions are not stored in cookies, it can lead to the creation and constant eviction of millions of sessions solely for the purpose of storing a CSRF token. To address this issue, Rails has added a new configuration option that allows a lambda to be provided that can store the CSRF token in a custom location.
You can also implement custom strategy classes for CSRF token storage:
16. Keyword arguments for system tests screenshot helper.
With this pull request, we can now selectively screenshot or dump the HTML of tests with the
screenshot: keyword arguments, as opposed to collectively dumping the HTML or screenshots when system tests run.
Here are some concrete examples:
17. Encrypted attributes on columns with default values.
Previously, reading encrypted attributes defined on columns with default values would raise an error unless
config.active_record.encryption.support_unencrypted_data was enabled because the contents of these columns were not encrypted. These values will now be encrypted at the time of record creation regardless of the config settings.
18. Pattern matching for ActiveModel [=Reverted=].
Update: This PR was reverted. Thanks to zverok_kha for the heads-up. A new gem replaced this feature for now.
Probably the most loved of 2022, this pull request introduces a pattern matching interface for hash patterns in Ruby versions 2.7 and later, enabling users to perform pattern matching on any object that includes the
ActiveModel::AttributeMethods module, such as
You can do interesting stuff like:
Here’s another example:
db_runtime added to Active Job instrumentation.
This pull request introduces
db_runtime to the notification payload of the
db_runtime tracks the total time (ms) spent on database queries during job execution, allowing for a better understanding of how a job’s time is spent.
20. Validity check for PostgreSQL indexes added.
Creating indexes this way for example
add_index :account, :active, algorithm: :concurrently may result in an invalid index. You can now check if an index is valid:
21. Exclusion constraints are now supported.
Although for PostgreSQL only, this extends Active Record’s migration or schema dumping to support PostgreSQL exclusion constraints.
Messageverifier gets a
urlsafe: initialization option.
MessageEncryptor constructors now accept a
:urlsafe option. When enabled, this option ensures that messages use a URL-safe encoding. When you pass
urlsafe: true to the initializers, you’ll get URL-safe strings in response.
This change adds that ability to call
in_batches with the specified ordering.
It honours the ordering now when it didn’t before. Should I call this a bug fix or a feature?
db:prepare can load the schema of an empty database.
Previously, if a database existed but had not been populated with tables,
db:prepare would run all migrations. Now
db:prepare will load the schema when an uninitialized database exists and dump schema after migrations.
25. Specify the parent class of a job with a job generator.
Rails added a
--parent option to the job generator to specify the parent class of a job. There’s now a superclass option in the job generator.
It’s possible now to do:
datetime_field gets a new
According to input elements of type time browsers render time differently if you format time without the “seconds” bit. This PR adds an option to omit the seconds part of the formatted time with
So something like this:
Will now generate:
27. Rails added support for Common Table Expressions.
You can now build sophisticated queries with Common Table Expressions using the
.with query method on models. The
.with allows the usage of Active Record relations without the need to manually build
28. Pre-defined variants for previews allowed now.
This pull request introduces the capability to use pre-defined variants when calling the
representation methods on an attachment. This allows for greater flexibility and customization when working with attachments.
For instance, you can now specify which variant of an attachment you want to use when generating a
And then use the defined variant like so:
routes --unused option to detect dormant routes.
Over time, a Rails app can become slow to boot simply because of how many routes it has. This new option for the
routes command can be used to detect routes that are drawn but aren’t valid.
30. Templates can now define which locals they accept.
This pull request adds the ability for templates to have required arguments with default values. Before this update, templates would accept any locals as keyword arguments, it’s now possible to define the specific locals that a template will accept with a magic comment.
This enhancement allows for greater control and customization of template behaviour and functionality.
Previously a partial could look like this:
Now, the same partial dons a simpler look:
And that brings us to the end of part one in the series: This Week In Rails Wrapped: A Summary Of Features Coming To Rails 7.1. This and the other two posts I’m working on are just a scratch on the surface of what’s coming in Rails 7.1. There are countless more features I haven’t covered. It’s important to also mention that I didn’t cover bug fixes and performance improvements.
I believe I can speak for other Rails developers when I say we’re grateful to all the 485 contributors that made this possible.
Special thanks to the This Week In Rails team, namely Greg Molnar, Petrik de Heus, Wojciech Wnętrzak and yours truly for making it easier to track and bring you all of these changes. You can subscribe to This Week In Rails going forward to get weekly updates like these in your email.
On Hacker News, the general sentiment regarding Rails in relation to this post has been positive.