Hi, it’s Vipul. Let’s explore this week’s changes in the Rails codebase.
Nominations are open for the 2026 Rails Luminary Awards
The Rails Foundation announced that nominations are open through August 21.
The awards recognize people who have significantly advanced Rails for the
benefit of the community.
Rails versions 7.2.3.2, 8.0.5.1, and 8.1.3.1 have been released
These security releases address a possible arbitrary file read and remote code
execution vulnerability in Active Storage variant processing. Please upgrade
as soon as possible.
Stop filtering i18n paths on initialize
Removes redundant path-globbing work during i18n initialization, cutting the
load time from 400 ms to about 250 ms in one application with thousands of
locale files.
Pass scheme to token authentication block in http_authentication
Token authentication methods now yield the authentication scheme as a
normalized symbol to the authentication block. They also support requiring a
specific scheme and returning the appropriate RFC 9110 challenge response.
Make lazy route loading thread-safe
Route drawing state moved from a boolean to a three-state flag guarded by a
reentrant Monitor. This fixes a race where concurrent threads could dispatch
requests against a half-drawn route set.
Deprecate TransactionState predicates, positional arguments to #insert, and binds passed to to_sql
A few cleanup deprecations landed this week:
TransactionState#fully_committed?, #fully_rolledback?, #fully_completed?,
and #nullify! are deprecated in favor of #committed?, #rolledback?, and
#completed?.pk, id_value, and sequence_name arguments to #insert
are deprecated. Callers can use returning: in place of pk.binds argument to to_sql is now deprecated instead of
being silently ignored.Extract table_name: as an explicit keyword argument in join table helpers
Migration join table helpers now accept table_name: as an explicit keyword
argument instead of removing it from an options hash as a side effect.
Resolve the single best template without sorting the whole set
Template resolution now finds the best match in one pass and binds locals only
for the winner instead of sorting and binding every candidate.
Support a single column name for #insert’s returning:
returning: now accepts a single column name and returns that column’s value
directly. Previously it accepted only arrays, forcing callers to unwrap a
one-element result.
Allow thread_mattr readers and writers to be used in a Ractor
Removes memoization of the per-thread key so thread_mattr readers and writers
work safely in Ractors. Access remains in the nanosecond range despite the
additional lookup.
Make controller middleware Ractor-safe
Uses a copy-on-write approach so controller middleware stacks can be shared
safely across Ractors. A proxy refreezes the stack after direct method calls.
Refactor insert returning: handling to take QueryIntent directly
Insert RETURNING handling moved from raw SQL string manipulation to
QueryIntent. Arel-based inserts can now set RETURNING directly on the AST.
Rename arel to arel_or_sql
Connection methods such as insert, update, delete, and explain accept
either an Arel manager or a raw SQL string but used inconsistent parameter
names. They now consistently use arel_or_sql.
Show parameter markers for casted binds in SQL logs and EXPLAIN
SQL logs and EXPLAIN output now show casted binds with positional markers such
as $1 instead of [nil, value], making each value’s position clear.
You can view the whole list of changes here.
We had 25 contributors to the Rails codebase this past week!
Until next time!
Subscribe to get these updates mailed to you.