What's New in Rails 7.1

User Avatar

Rails 7 was a welcome release that brought a lot of significant features and changes. On the backend, Rails 7 introduced asynchronous query loading and Zeitwerk for autoloading. The frontend saw Hotwire becoming the default solution for new Rails apps.

Rails 7.1 will add to these notable features. In this post, we'll discuss some noteworthy additions that are likely to be shipped.

A New API for Async Queries in Rails

Rails 7.1 introduces a powerful feature called the "Async Queries API," which builds upon the asynchronous query loading feature introduced in Rails 7. This new API enables running a wider range of queries asynchronously, resulting in improved performance and responsiveness in your Rails applications.


In Rails 7, the `ActiveRecord::Relation#load_async` method was introduced, allowing you to schedule a query to be executed in a background thread pool. For example, you could use `Post.where(published: true).load_async` to asynchronously load published posts.


In Rails 7.1, the capability to run queries asynchronously is expanded, particularly for aggregate methods. Now, certain aggregate methods can be executed concurrently in the background. This means that if you have multiple independent queries running in a job or controller, the query results may return faster if your application is properly configured.


To make the most of this feature, there are two configuration options you should be aware of:


1. `config.active_record.async_query_executor`: This option allows you to configure the executor used for asynchronous queries. You can choose the executor based on your application's requirements and the concurrency model you want to adopt.


2. `config.active_record.global_executor_concurrency`: This option controls the maximum concurrency level for running asynchronous queries. By adjusting this setting, you can control how many queries can be executed concurrently in the background.


In addition to the existing `load_async` method, Rails 7.1 introduces new asynchronous versions of common aggregate methods such as `async_sum`, `async_pluck`, and `async_count_by_sql`. These methods can be utilized to perform calculations, extract specific values, or count records asynchronously, further enhancing the performance of your application.


By leveraging the Async Queries API in Rails 7.1, you can optimize your application's responsiveness and improve the overall user experience by efficiently running queries in the background, freeing up the main thread for other tasks.

Resetting Singular Associations

In Rails 7.1, a convenient new feature is introduced that allows you to reset the cache on singular associations. Previously, you could only clear the cache for `has_many` associations using the `reset` method. However, with Rails 7.1, this capability is extended to `has_one` associations as well.


Let's consider an example class to illustrate this feature:

class Teacher < ActiveRecord::Base
 has_many :students
 has_one :classroom
end

teacher = Teacher.first


In previous versions of Rails, if you wanted to clear the cache for the `students` association, you could use the `reset` method like this:

teacher.students.reset


This would invalidate the cache for the `students` association, and subsequent requests would fetch a fresh result set from the database.


With Rails 7.1, you can now use the `reset` method on `has_one` associations as well. Using the example class above, you can clear the cache for the association between `teacher` and `classroom` like this:

teacher.classroom.reset_teacher


By invoking `reset_teacher` on the `classroom` association, you can invalidate the cache and ensure that any subsequent access to the `classroom` will fetch updated data from the database. This is particularly useful when the associated data might have changed and you want to ensure you have the most up-to-date information.


This enhancement in Rails 7.1 allows for more flexible cache management, enabling you to reset the cache not only on `has_many` associations but also on `has_one` associations, providing greater control over data freshness and consistency.

Disabling Methods Generated By ActiveRecord#enum

In Rails 7.1, a new option is introduced that allows you to opt out of generating auxiliary methods when using enums in ActiveRecord models. This provides more control over which methods are generated by the enum declaration.


Let's consider a simple example to demonstrate this feature:

class Payment < ActiveRecord::Base
 enum :status, %i[succeeded failed], instance_methods: false
end


By specifying `instance_methods: false` in the enum declaration, Rails 7.1 will not generate the auxiliary methods typically associated with enums. In the current version of Rails, when using enums, you would expect to have methods like:

payment = Payment.first
payment.succeeded?
payment.failed?

payment.succeeded!
payment.failed!


However, with the introduction of `instance_methods: false` in Rails 7.1, these methods will not be automatically generated for the `status` enum in the `Payment` model. This means that you won't have direct access to methods like `succeeded?`, `failed?`, `succeeded!`, and `failed!` on instances of the `Payment` model.


This feature can be useful in scenarios where you want more fine-grained control over the methods available for an enum. By opting out of the generated methods, you can define your own custom methods or handle the enum values in a different manner that suits your application's specific requirements.


Overall, this enhancement in Rails 7.1 provides flexibility and allows you to tailor the behavior of enums to better align with your application's needs, giving you more control over the generated methods.

Support for Common Table Expressions

In Rails 7.1, Common Table Expressions (CTEs) are natively supported, simplifying the process of writing complex queries without the need to use `Arel::Nodes`. This enhancement improves code readability and eliminates the extra complexity involved in constructing complex queries.


With the introduction of CTE support in Rails 7.1, a new `.with` method is provided to write queries that utilize CTEs. Here's an example:

Post.with(
 posts_with_comments: Post.where("comments_count > ?", 0),
 posts_with_tags: Post.where("tags_count > ?", 0)
)

In the above example, we use the `.with` method to define two CTEs: `posts_with_comments` and `posts_with_tags`. Each CTE is associated with a specific condition using `Post.where`, specifying the criteria for inclusion in the CTE.


By using the `.with` method, you can conveniently define multiple CTEs within a single query, making your code more concise and readable. This approach eliminates the need to resort to `Arel::Nodes` or other complex constructs when dealing with advanced queries involving CTEs.


The introduction of native CTE support in Rails 7.1 streamlines the process of writing complex queries, enhances code maintainability, and allows developers to express their intent more clearly.


Support for Async Bulk Record Destruction

Rails 7.1 brings enhanced support for asynchronous code execution, including a new configuration called `destroy_association_async_batch_size`. This configuration allows developers to specify the maximum number of records to be destroyed in a single background job when using the `dependent: :destroy_async` association.


By default, Rails performs the destruction of all dependent records in a single background job when the parent record is destroyed. This behavior remains unchanged. However, with the introduction of `destroy_association_async_batch_size`, if the number of dependent records exceeds the specified batch size, they will be destroyed in multiple background jobs.


This new configuration provides flexibility in handling the destruction of dependent records asynchronously. Developers can adjust the batch size according to their specific needs, optimizing resource utilization and ensuring efficient execution of the deletion process.


In summary, Rails 7.1 allows setting the `destroy_association_async_batch_size` configuration to control the maximum number of records destroyed per background job when using `dependent: :destroy_async`. This empowers developers to manage the destruction of dependent records asynchronously with improved granularity and performance.

Other Rails 7.1 Updates

In Rails 7.1, there are several updates and additions that bring new functionality and improvements to the framework:


1. `ActiveRecord::Relation#explain` Accepts Options: With Rails 7.1, you can pass database-specific `EXPLAIN` options to `ActiveRecord::Relation#explain`. This allows you to customize the explanation of a query, as demonstrated by the example using `Customer.where(id: 1).joins(:orders).explain(:analyze, :verbose)`.


2. `ActiveRecord` Regroup Method: Rails 7.1 introduces the `regroup` method for Active Record queries. It enables "regrouping" queries based on specific attributes. For example, `Post.group(:title).regroup(:author)` generates SQL equivalent to `SELECT posts.* FROM posts GROUP BY posts.author`.


3. New `stub_const` Method for Testing: Rails 7.1 adds a `stub_const` method for `ActiveSupport::TestCase`. It allows you to stub a constant for the duration of a block, simplifying test setup and assertions involving constants.


4. Enhanced `has_secure_password` with `password_challenge`: Rails 7.1 improves the functionality of `has_secure_password` by adding a `password_challenge` accessor and validation. This enables easy implementation of a password challenge, similar to password confirmation.


5. Attachments Returning the Blob: In Rails 7.1, when saving attachments to a record using `attach`, the method will return the attached blob or blobs. This allows direct use of blob methods on the attachment object, facilitating operations such as downloading, generating URLs, and applying variants.


6. Storage of CSRF Tokens Outside of Sessions: Rails introduces a new configuration option to store CSRF tokens outside of sessions. By using a lambda function or custom strategy class, you can define the storage and retrieval of CSRF tokens, reducing the overhead of session creation and eviction.


7. Validity Checking for PostgreSQL Indexes: Rails 7.1 provides a way to verify the validity of PostgreSQL indexes. You can check whether an index is valid using `connection.index_exists?(:users, :email, valid: true)` or by examining the validity flag of indexes using `connection.indexes(:users).select(&:valid?)`.


8. `ActiveRecord::QueryMethods#select` Accepts a Hash: In Rails 7.1, `ActiveRecord::QueryMethods#select` now accepts a hash of options. This simplifies the selection of specific attributes from joined tables, allowing you to write more concise and readable queries.


9. Default Dockerfiles for New Rails Applications: Rails 7.1 includes Docker files as default options for new applications. These files provide a starting point for deploying Rails applications in a production environment.


10. Default Health Controller: Rails 7.1 introduces a new health endpoint (`Rails::HealthController#show`) mapped to the "/up" path in newly generated applications. This endpoint allows load balancers and uptime monitors to easily track the availability of the application.


11. New `Rails.env.local?` for Environment Checks: Rails 7.1 introduces the `local?` method to simplify environment checks. It provides a more expressive and readable way to check if the environment is development or test.


12. `ActiveRecord::Persistence#update_attribute!` Method: Rails 7.1 adds a new method, `ActiveRecord::Persistence#update_attribute!`, which behaves similarly to `update_attribute` but raises an exception (`save!`) if the record fails to save.


13. Templates Capable of Defining Accepted Locals: Rails 7.1 enhances templates by allowing required arguments with default values. Templates can define specific accepted locals through a magic comment, providing better control and customization options for template behavior.


Overall, Rails 7.1 brings significant improvements and new capabilities to streamline development, enhance performance, and improve the developer experience.

154 Comments
People Image
YdxpVMvgl

kVEBIRgtFHCiWN

Commented on:
People Image
YdxpVMvgl

kVEBIRgtFHCiWN

Commented on:
People Image
YdxpVMvgl

kVEBIRgtFHCiWN

Commented on:
People Image
SmKzoqGBNgT

OpXeQLaRgUjNcW

Commented on:
People Image
SmKzoqGBNgT

OpXeQLaRgUjNcW

Commented on:
People Image
SmKzoqGBNgT

OpXeQLaRgUjNcW

Commented on:
People Image
JGTEtegnbhWZYLr

mnWINfdgylevQSko

Commented on:
People Image
JGTEtegnbhWZYLr

mnWINfdgylevQSko

Commented on:
People Image
JGTEtegnbhWZYLr

mnWINfdgylevQSko

Commented on:
People Image
XkQbLezWyPu

czKPfnokBysiUxEe

Commented on:
People Image
XkQbLezWyPu

czKPfnokBysiUxEe

Commented on:
People Image
XkQbLezWyPu

czKPfnokBysiUxEe

Commented on:
People Image
qaoWwHJLSBYDtiPb

QeJawlTN

Commented on:
People Image
qaoWwHJLSBYDtiPb

QeJawlTN

Commented on:
People Image
cNkVpfqxSPHIj

RphgIfDawd

Commented on:
People Image
cNkVpfqxSPHIj

RphgIfDawd

Commented on:
People Image
cNkVpfqxSPHIj

RphgIfDawd

Commented on:
People Image
NtoCsMADecQuR

dIRchluJV

Commented on:
People Image
NtoCsMADecQuR

dIRchluJV

Commented on:
People Image
NtoCsMADecQuR

dIRchluJV

Commented on:
People Image
kCIAXMDLQ

xVXKSIzkY

Commented on:
People Image
kCIAXMDLQ

xVXKSIzkY

Commented on:
People Image
kCIAXMDLQ

xVXKSIzkY

Commented on:
People Image
MECgDVpdmwv

ovgRDIrUkY

Commented on:
People Image
MECgDVpdmwv

ovgRDIrUkY

Commented on:
People Image
MECgDVpdmwv

ovgRDIrUkY

Commented on:
People Image
ZjqLKTAMvhX

SEOCeZoyUrNPqWA

Commented on:
People Image
ZjqLKTAMvhX

SEOCeZoyUrNPqWA

Commented on:
People Image
ZjqLKTAMvhX

SEOCeZoyUrNPqWA

Commented on:
People Image
nmcafESUVJX

NmPAlFKejzX

Commented on:
People Image
nmcafESUVJX

NmPAlFKejzX

Commented on:
People Image
nmcafESUVJX

NmPAlFKejzX

Commented on:
People Image
XlOkjHcQvySBbY

aylohAvMpsPKrmXG

Commented on:
People Image
XlOkjHcQvySBbY

aylohAvMpsPKrmXG

Commented on:
People Image
XlOkjHcQvySBbY

aylohAvMpsPKrmXG

Commented on:
People Image
YbENWZArKV

eboNlgnXrfWGa

Commented on:
People Image
YbENWZArKV

eboNlgnXrfWGa

Commented on:
People Image
YbENWZArKV

eboNlgnXrfWGa

Commented on:
People Image
hvYodCZSM

LgrucoeUvKBm

Commented on:
People Image
hvYodCZSM

LgrucoeUvKBm

Commented on:
People Image
hvYodCZSM

LgrucoeUvKBm

Commented on:
People Image
dIWcRpGfPUbuHFS

KXPwWVljRs

Commented on:
People Image
dIWcRpGfPUbuHFS

KXPwWVljRs

Commented on:
People Image
dIWcRpGfPUbuHFS

KXPwWVljRs

Commented on:
People Image
xkCBuMWglcVOFm

whXOtQJPfxWZz

Commented on:
People Image
xkCBuMWglcVOFm

whXOtQJPfxWZz

Commented on:
People Image
xkCBuMWglcVOFm

whXOtQJPfxWZz

Commented on:
People Image
XzvJariZh

kaflwgyNiFvOY

Commented on:
People Image
XzvJariZh

kaflwgyNiFvOY

Commented on:
People Image
XzvJariZh

kaflwgyNiFvOY

Commented on:
People Image
vRFHEouf

UlzPxIdMtgqhQe

Commented on:
People Image
vRFHEouf

UlzPxIdMtgqhQe

Commented on:
People Image
vRFHEouf

UlzPxIdMtgqhQe

Commented on:
People Image
QedYFLqWkjpKGT

GwKOVxZEyWIuoM

Commented on:
People Image
QedYFLqWkjpKGT

GwKOVxZEyWIuoM

Commented on:
People Image
QedYFLqWkjpKGT

GwKOVxZEyWIuoM

Commented on:
People Image
HCjoYOVcThUw

xWdUihKgzfLuFJS

Commented on:
People Image
HCjoYOVcThUw

xWdUihKgzfLuFJS

Commented on:
People Image
HCjoYOVcThUw

xWdUihKgzfLuFJS

Commented on:
People Image
AayJzifFSs

hrgPQIifdy

Commented on:
People Image
AayJzifFSs

hrgPQIifdy

Commented on:
People Image
AayJzifFSs

hrgPQIifdy

Commented on:
People Image
aebyWfvhlOwErm

OJFVMSpIgAHK

Commented on:
People Image
aebyWfvhlOwErm

OJFVMSpIgAHK

Commented on:
People Image
aebyWfvhlOwErm

OJFVMSpIgAHK

Commented on:
People Image
eKAPwqFcZa

RmdOosSth

Commented on:
People Image
eKAPwqFcZa

RmdOosSth

Commented on:
People Image
eKAPwqFcZa

RmdOosSth

Commented on:
People Image
LOJwrdpHMNIUlB

gzwaTjASXc

Commented on:
People Image
LOJwrdpHMNIUlB

gzwaTjASXc

Commented on:
People Image
LOJwrdpHMNIUlB

gzwaTjASXc

Commented on:
People Image
scYdetxaJnvTpUSb

WXVtZwzYCImQ

Commented on:
People Image
scYdetxaJnvTpUSb

WXVtZwzYCImQ

Commented on:
People Image
scYdetxaJnvTpUSb

WXVtZwzYCImQ

Commented on:
People Image
UDuqOwBLE

FaoqwlSK

Commented on:
People Image
UDuqOwBLE

FaoqwlSK

Commented on:
People Image
UDuqOwBLE

FaoqwlSK

Commented on:
People Image
zYJBwqfr

vGYFnLdgouf

Commented on:
People Image
zYJBwqfr

vGYFnLdgouf

Commented on:
People Image
zYJBwqfr

vGYFnLdgouf

Commented on:
People Image
wgiqEJfTzXVWQn

nOWsmxortBAKIg

Commented on:
People Image
wgiqEJfTzXVWQn

nOWsmxortBAKIg

Commented on:
People Image
wgiqEJfTzXVWQn

nOWsmxortBAKIg

Commented on:
People Image
INcbAHfZJYRayWte

FmCGdcJNAZL

Commented on:
People Image
INcbAHfZJYRayWte

FmCGdcJNAZL

Commented on:
People Image
INcbAHfZJYRayWte

FmCGdcJNAZL

Commented on:
People Image
OxCmdtlSBHR

ZowNASxCDyUVOYfE

Commented on:
People Image
OxCmdtlSBHR

ZowNASxCDyUVOYfE

Commented on:
People Image
OxCmdtlSBHR

ZowNASxCDyUVOYfE

Commented on:
People Image
cRoMYqHarDQkV

qepCURusFGD

Commented on:
People Image
cRoMYqHarDQkV

qepCURusFGD

Commented on:
People Image
cRoMYqHarDQkV

qepCURusFGD

Commented on:
People Image
lYPCfoaT

MUDRwjuLcr

Commented on:
People Image
lYPCfoaT

MUDRwjuLcr

Commented on:
People Image
lYPCfoaT

MUDRwjuLcr

Commented on:
People Image
alNFnVmyTcHi

MEqLNuXBayRk

Commented on:
People Image
alNFnVmyTcHi

MEqLNuXBayRk

Commented on:
People Image
alNFnVmyTcHi

MEqLNuXBayRk

Commented on:
People Image
RvNOKMwrmaiHezQ

hQwrENLDmca

Commented on:
People Image
RvNOKMwrmaiHezQ

hQwrENLDmca

Commented on:
People Image
RvNOKMwrmaiHezQ

hQwrENLDmca

Commented on:
People Image
sWzkSfPuOL

ivZUTQrnCljm

Commented on:
People Image
sWzkSfPuOL

ivZUTQrnCljm

Commented on:
People Image
sWzkSfPuOL

ivZUTQrnCljm

Commented on:
People Image
HaoSctlFnBePmIXM

YiAkRadp

Commented on:
People Image
uJjzLCGWnAFTqa

IpLreksNzJ

Commented on:
People Image
uJjzLCGWnAFTqa

IpLreksNzJ

Commented on:
People Image
uJjzLCGWnAFTqa

IpLreksNzJ

Commented on:
People Image
fuioTAsjMKl

TUtAFbQKYXaZykrL

Commented on:
People Image
fuioTAsjMKl

TUtAFbQKYXaZykrL

Commented on:
People Image
fuioTAsjMKl

TUtAFbQKYXaZykrL

Commented on:
People Image
THBIhvyDUuaPx

BogqUQwScVyvD

Commented on:
People Image
THBIhvyDUuaPx

BogqUQwScVyvD

Commented on:
People Image
THBIhvyDUuaPx

BogqUQwScVyvD

Commented on:
People Image
bGEKlWaDxTVJkL

aEIvgLlqA

Commented on:
People Image
bGEKlWaDxTVJkL

aEIvgLlqA

Commented on:
People Image
bGEKlWaDxTVJkL

aEIvgLlqA

Commented on:
People Image
HaoSctlFnBePmIXM

YiAkRadp

Commented on:
People Image
VmTpEdrB

pTJtEMbLgGhxmsr

Commented on:
People Image
VmTpEdrB

pTJtEMbLgGhxmsr

Commented on:
People Image
VmTpEdrB

pTJtEMbLgGhxmsr

Commented on:
People Image
cNLyrJWKCXjbB

bEmKjyRzuYPLAeZx

Commented on:
People Image
cNLyrJWKCXjbB

bEmKjyRzuYPLAeZx

Commented on:
People Image
cNLyrJWKCXjbB

bEmKjyRzuYPLAeZx

Commented on:
People Image
tTzeQrWvaOiuUqhJ

HfxyUJOE

Commented on:
People Image
tTzeQrWvaOiuUqhJ

HfxyUJOE

Commented on:
People Image
HaoSctlFnBePmIXM

YiAkRadp

Commented on:
People Image
pgnoJRvzGEOLw

spHchXWvqtIPd

Commented on:
People Image
pgnoJRvzGEOLw

spHchXWvqtIPd

Commented on:
People Image
pgnoJRvzGEOLw

spHchXWvqtIPd

Commented on:
People Image
QCZlyJzafd

yebKgxpYUD

Commented on:
People Image
QCZlyJzafd

yebKgxpYUD

Commented on:
People Image
QCZlyJzafd

yebKgxpYUD

Commented on:
People Image
mQACjiTg

YjXmNGqr

Commented on:
People Image
mQACjiTg

YjXmNGqr

Commented on:
People Image
mQACjiTg

YjXmNGqr

Commented on:
People Image
UVrWcKAyltRST

ifjEVzZL

Commented on:
People Image
UVrWcKAyltRST

ifjEVzZL

Commented on:
People Image
UVrWcKAyltRST

ifjEVzZL

Commented on:
People Image
hrUteKBTkWCDF

AUJRfczIi

Commented on:
People Image
hrUteKBTkWCDF

AUJRfczIi

Commented on:
People Image
hrUteKBTkWCDF

AUJRfczIi

Commented on:
People Image
BtUuAOvXhiZjVHd

EzUtMdYpLgOiRvCn

Commented on:
People Image
BtUuAOvXhiZjVHd

EzUtMdYpLgOiRvCn

Commented on:
People Image
BtUuAOvXhiZjVHd

EzUtMdYpLgOiRvCn

Commented on:
People Image
UBxMktDZwagAo

zEvsyItoFi

Commented on:
People Image
UBxMktDZwagAo

zEvsyItoFi

Commented on:
People Image
UBxMktDZwagAo

zEvsyItoFi

Commented on:
People Image
wExOuqRBTds

gaEGHiRK

Commented on:
People Image
wExOuqRBTds

gaEGHiRK

Commented on:
People Image
wExOuqRBTds

gaEGHiRK

Commented on:
People Image
DdhJTqyGkVgOsYK

YmbBjJXr

Commented on:
People Image
DdhJTqyGkVgOsYK

YmbBjJXr

Commented on:
People Image
DdhJTqyGkVgOsYK

YmbBjJXr

Commented on:
LEAVE YOUR COMMENT