Friday, September 25, 2026

See you in Lisbon!

Posted by Claudio Baccigalupo

Hi, it’s Claudio Baccigalupo with your updates on the Rails codebase.

What a week! Rails World took over Austin with more than a thousand attendees from all over the world. I was able to meet my fellow newsletter editors and to thank the amazing Amanda Perino for another successful conference.

This Week in Rails + Amanda Perino

And now… let’s see what changed on main in the last seven days.

Newly released: Rails 8.1.4 and 7.2.4
Take a look at their CHANGELOG (v8.1.4 and v7.2.4) for all the new features.

The Asset Pipeline Guide rewritten
Now with a bigger focus on how a developer would use the asset pipeline and Propshaft: check it out. Then go read the Active Record composite primary keys guide which has also been improved as part of the Rails Foundation documentation project.

New framework default to compile HTML+ERB templates through Herb
config.action_view.erb_implementation now accepts :herb and :erubi, and the 8.2 framework defaults set :herb. New applications, and applications running config.load_defaults 8.2, compile templates with the HTML format through ERB::Herb and every other format through Erubi.

Deprecate supports_datetime_with_precision?
The method was added 11 years ago to gate the :precision option on datetime and time columns. Since MySQL 5.5 support was dropped two years ago, every database Active Record supports handles precision so the method is not needed.

Deprecate ActiveRecord::Callbacks::CALLBACKS
The CALLBACKS constant has been outdated for a long time, and is only referenced in tests. Anything driven off the constant silently skips callbacks such as before_commit. It is deprecated with no replacement and will be removed in Rails 9.

Fix BigInteger casting truncating strings to 16 bytes
BigInteger returns twice the precision of Integer which leaves room for a sign or a slug suffix. For decimal(20, 0) that is 40 bytes. A BigInteger with no precision uses twice the largest precision databases accept (2000 bytes on PostgreSQL).

Restore integer bounds from JSON schema cache
Restore the minimum and maximum values when loading the integer type from JSON to avoid raising FrozenError.

Fix non-ASCII strict locals defaults in ASCII-only templates
A non-ASCII default in the locals: magic comment was rendering the wrong characters when the template body is ASCII-only. For instance:

<%# locals: (label: "café") %>
<%= label %>

would render caf�� with no exception raised.

Fix BroadcastLogger#tagged when broadcasting to multiple tagging loggers
Defines #tagged directly on BroadcastLogger. Without a block, returns a new BroadcastLogger whose tagging-capable broadcasts are tagged. With a block, nests each tagging logger’s own block form and yields the broadcast logger exactly once with every tag active. Follow-up PR 58850 improves it by making logger_tagged_by_active_job? check formatter.respond_to?(:current_tags) before calling it.

Avoid aliasing Kernel#respond_to? in ActiveModel::AttributeMethods
Define respond_to_without_attributes? with define_method and Kernel.instance_method(:respond_to?) instead of alias. This copies Kernel#respond_to? into the module in the same way the alias did, without the deprecated lookup, so the behavior is unchanged.

Schema-qualify the regclass cast in check_all_foreign_keys_valid!
Qualifies the cast with the constraint’s schema: '%2$I.%3$I'::regclass.

Manually specify security validator in herb checker
Changes the checker so behaviour is consistent across herb versions.

Add Manitoba time zone mapping
Adds a friendly zone mapping: Manitoba → America/Winnipeg

Backport alias fallback fixes for Active Model to 8-1-stable
Three changes bringing recent fixes to attribute_methods.rb, serialization.rb, validations.rb from main to the stable 8.1 branch.

Make ActionController::ParamsWrapper._wrapper_options ractor safe
ActionController::ParamsWrapper::Options now freezes deeply and clears its mutex so it may be shared properly.

Active Record Ractor-friendly connection handling
Introduces a connection handler / pool / proxy that is used in place of the default when the application is running a query on the non-main Ractor.

Use standard input for MySQL db:schema:load
MySQLDatabaseTasks#structure_load now passes the structure file to the client’s standard input, as SQLiteDatabaseTasks#structure_load already does. Reading SQL from standard input needs no client-side command, so the --commands setting does not matter, and structure_load_flags are passed through unchanged.

Drop needless schema qualification from db/schema.rb on PostgreSQL
An extension is dumped with its schema only when that schema was picked at CREATE EXTENSION time, through the SCHEMA clause or the default creation schema. When the control file fixes the schema, as pg_available_extension_versions reports, the extension is dumped by name alone and CREATE EXTENSION takes care of the schema on load. An extension installed with CREATE EXTENSION ... SCHEMA, such as enable_extension "heroku_ext.pgcrypto", is dumped as before.

Drop the explicit SET FOREIGN_KEY_CHECKS statements from MySQL db:schema:load
structure_load no longer sends the SET FOREIGN_KEY_CHECKS statements, so the command becomes mysql --execute "SOURCE db/structure.sql" --database app_development. The checks are off while the file runs and the setting ends with the session, as before.

Fix Server-Timing double-counting of nested same-name events
ActionDispatch::ServerTiming subscribes to Active Support notifications and writes a Server-Timing header. The value was correct for a single event but wrong when many events share a name and nest.

Avoid deadlocks on concurrent find_or_create_by calls in MySQL
Fixes a MySQL deadlock in concurrent find_or_create_by and create_or_find_by (including their bang variants) by using a shared lock when reading back a record after a duplicate insert.

You can view the whole list of changes here.
We had 27 contributors to the Rails codebase this past week!

Until next time!

Subscribe to get these updates mailed to you.