8.1.0.rc1
Pre-releaseActive Support
-
Remove deprecated passing a Time object to
Time#since.Rafael Mendonça França
-
Remove deprecated
Benchmark.msmethod. It is now defined in thebenchmarkgem.Rafael Mendonça França
-
Remove deprecated addition for
Timeinstances withActiveSupport::TimeWithZone.Rafael Mendonça França
-
Remove deprecated support for
to_timeto preserve the system local time. It will now always preserve the receiver
timezone.Rafael Mendonça França
-
Deprecate
config.active_support.to_time_preserves_timezone.Rafael Mendonça França
-
Standardize event name formatting in
assert_event_reportederror messages.The event name in failure messages now uses
.inspect(e.g.,name: "user.created")
to matchassert_events_reportedand provide type clarity between strings and symbols.
This only affects tests that assert on the failure message format itself.George Ma
-
Fix
Enumerable#soleto return the full tuple instead of just the first element of the tuple.Olivier Bellone
-
Fix parallel tests hanging when worker processes die abruptly.
Previously, if a worker process was killed (e.g., OOM killed,
kill -9) during parallel
test execution, the test suite would hang forever waiting for the dead worker.Joshua Young
-
Add
config.active_support.escape_js_separators_in_json.Introduce a new framework default to skip escaping LINE SEPARATOR (U+2028) and PARAGRAPH SEPARATOR (U+2029) in JSON.
Historically these characters were not valid inside JavaScript literal strings but that changed in ECMAScript 2019.
As such it's no longer a concern in modern browsers: https://caniuse.com/mdn-javascript_builtins_json_json_superset.Étienne Barrié, Jean Boussier
-
Fix
NameErrorwhenclass_attributeis defined on instance singleton classes.Previously, calling
class_attributeon an instance's singleton class would raise
aNameErrorwhen accessing the attribute through the instance.object = MyClass.new object.singleton_class.class_attribute :foo, default: "bar" object.foo # previously raised NameError, now returns "bar"
Joshua Young
-
Introduce
ActiveSupport::Testing::EventReporterAssertions#with_debug_event_reporting
to enable event reporter debug mode in tests.The previous way to enable debug mode is by using
#with_debugon the
event reporter itself, which is too verbose. This new helper will help
clear up any confusion on how to test debug events.Gannon McGibbon
-
Add
ActiveSupport::StructuredEventSubscriberfor consuming notifications and
emitting structured event logs. Events may be emitted with the#emit_event
or#emit_debug_eventmethods.class MyStructuredEventSubscriber < ActiveSupport::StructuredEventSubscriber def notification(event) emit_event("my.notification", data: 1) end end
Adrianna Chang
-
ActiveSupport::FileUpdateCheckerdoes not depend onTime.nowto prevent unecessary reloads with time travel test helpersJan Grodowski
Active Model
-
Add
reset_token: { expires_in: ... }option tohas_secure_password.Allows configuring the expiry duration of password reset tokens (default remains 15 minutes for backwards compatibility).
has_secure_password reset_token: { expires_in: 1.hour }
Jevin Sew, Abeid Ahmed
Active Record
-
Add replicas to test database parallelization setup.
Setup and configuration of databases for parallel testing now includes replicas.
This fixes an issue when using a replica database, database selector middleware,
and non-transactional tests, where integration tests running in parallel would select
the base test database, i.e.db_test, instead of the numbered parallel worker database,
i.e.db_test_{n}.Adam Maas
-
Support virtual (not persisted) generated columns on PostgreSQL 18+
PostgreSQL 18 introduces virtual (not persisted) generated columns,
which are now the default unless thestored: trueoption is explicitly specified on PostgreSQL 18+.create_table :users do |t| t.string :name t.virtual :lower_name, type: :string, as: "LOWER(name)", stored: false t.virtual :name_length, type: :integer, as: "LENGTH(name)" end
Yasuo Honda
-
Optimize schema dumping to prevent duplicate file generation.
ActiveRecord::Tasks::DatabaseTasks.dump_allnow tracks which schema files
have already been dumped and skips dumping the same file multiple times.
This improves performance when multiple database configurations share the
same schema dump path.Mikey Gough, Hartley McGuire
-
Add structured events for Active Record:
active_record.strict_loading_violationactive_record.sql
Gannon McGibbon
-
Add support for integer shard keys.
# Now accepts symbols as shard keys. ActiveRecord::Base.connects_to(shards: { 1: { writing: :primary_shard_one, reading: :primary_shard_one }, 2: { writing: :primary_shard_two, reading: :primary_shard_two}, }) ActiveRecord::Base.connected_to(shard: 1) do # .. end
Nony Dutton
-
Add
ActiveRecord::Base.only_columnsSimilar in use case to
ignored_columnsbut listing columns to consider rather than the ones
to ignore.Can be useful when working with a legacy or shared database schema, or to make safe schema change
in two deploys rather than three.Anton Kandratski
-
Use
PG::Connection#close_prepared(protocol level Close) to deallocate
prepared statements when available.To enable its use, you must have pg >= 1.6.0, libpq >= 17, and a PostgreSQL
database version >= 17.Hartley McGuire, Andrew Jackson
-
Fix query cache for pinned connections in multi threaded transactional tests
When a pinned connection is used across separate threads, they now use a separate cache store
for each thread.This improve accuracy of system tests, and any test using multiple threads.
Heinrich Lee Yu, Jean Boussier
-
Fix time attribute dirty tracking with timezone conversions.
Time-only attributes now maintain a fixed date of 2000-01-01 during timezone conversions,
preventing them from being incorrectly marked as changed due to date shifts.This fixes an issue where time attributes would be marked as changed when setting the same time value
due to timezone conversion causing internal date shifts.Prateek Choudhary
-
Skip calling
PG::Connection#cancelincancel_any_running_query
when using libpq >= 18 with pg < 1.6.0, due to incompatibility.
Rollback still runs, but may take longer.Yasuo Honda, Lars Kanis
-
Don't add
id_valueattribute alias when attribute/column with that name already exists.Rob Lewis
Action View
-
The BEGIN template annotation/comment was previously printed on the same line as the following element. We now insert a newline inside the comment so it spans two lines without adding visible whitespace to the HTML output to enhance readability.
Before:
<!-- BEGIN /Users/siaw23/Desktop/rails/actionview/test/fixtures/actionpack/test/greeting.html.erb --><p>This is grand!</p>After:
<!-- BEGIN /Users/siaw23/Desktop/rails/actionview/test/fixtures/actionpack/test/greeting.html.erb --><p>This is grand!</p>Emmanuel Hayford
-
Add structured events for Action View:
action_view.render_templateaction_view.render_partialaction_view.render_layoutaction_view.render_collectionaction_view.render_start
Gannon McGibbon
-
Fix label with
foroption not getting prefixed by formnamespacevalueAbeid Ahmed, Hartley McGuire
-
Add
fetchpriorityto Link headers to match HTML generated bypreload_link_tag.Guillermo Iguaran
Action Pack
-
Add link-local IP ranges to
ActionDispatch::RemoteIpdefault proxies.Link-local addresses (
169.254.0.0/16for IPv4 andfe80::/10for IPv6)
are now included in the default trusted proxy list, similar to private IP ranges.Adam Daniels
-
remote_ipwill no longer ignore IPs in X-Forwarded-For headers if they
are accompanied by port information.Duncan Brown, Prevenios Marinos, Masafumi Koba, Adam Daniels
-
Add
action_dispatch.verbose_redirect_logssetting that logs where redirects were called from.Similar to
active_record.verbose_query_logsandactive_job.verbose_enqueue_logs, this adds a line in your logs that shows where a redirect was called from.Example:
Redirected to http://localhost:3000/posts/1 ↳ app/controllers/posts_controller.rb:32:in `block (2 levels) in create'Dennis Paagman
-
Add engine route filtering and better formatting in
bin/rails routes.Allow engine routes to be filterable in the routing inspector, and
improve formatting of engine routing output.Before:
> bin/rails routes -e engine_only No routes were found for this grep pattern. For more information about routes, see the Rails guide: https://guides.rubyonrails.org/routing.html.After:
> bin/rails routes -e engine_only Routes for application: No routes were found for this grep pattern. For more information about routes, see the Rails guide: https://guides.rubyonrails.org/routing.html. Routes for Test::Engine: Prefix Verb URI Pattern Controller#Action engine GET /engine_only(.:format) a#bDennis Paagman, Gannon McGibbon
-
Add structured events for Action Pack and Action Dispatch:
action_dispatch.redirectaction_controller.request_startedaction_controller.request_completedaction_controller.callback_haltedaction_controller.rescue_from_handledaction_controller.file_sentaction_controller.redirectedaction_controller.data_sentaction_controller.unpermitted_parametersaction_controller.fragment_cache
Adrianna Chang
-
URL helpers for engines mounted at the application root handle
SCRIPT_NAMEcorrectly.Fixed an issue where
SCRIPT_NAMEis not applied to paths generated for routes in an engine
mounted at "/".Mike Dalessio
-
Update
ActionController::Metal::RateLimitingto support passing method names to:byand:withclass SignupsController < ApplicationController rate_limit to: 10, within: 1.minute, with: :redirect_with_flash private def redirect_with_flash redirect_to root_url, alert: "Too many requests!" end end
Sean Doyle
-
Optimize
ActionDispatch::Http::URL.build_host_urlwhen protocol is included in host.When using URL helpers with a host that includes the protocol (e.g.,
{ host: "https://example.com" }),
skip unnecessary protocol normalization and string duplication since the extracted protocol is already
in the correct format. This eliminates 2 string allocations per URL generation and provides a ~10%
performance improvement for this case.Joshua Young, Hartley McGuire
-
Allow
action_controller.loggerto be disabled by setting it tonilorfalseinstead of always defaulting toRails.logger.Roberto Miranda
Active Job
-
Add structured events for Active Job:
active_job.enqueuedactive_job.bulk_enqueuedactive_job.startedactive_job.completedactive_job.retry_scheduledactive_job.retry_stoppedactive_job.discardedactive_job.interruptactive_job.resumeactive_job.step_skippedactive_job.step_startedactive_job.step
Adrianna Chang
Action Mailer
-
Add structured events for Action Mailer:
action_mailer.deliveredaction_mailer.processed
Gannon McGibbon
Action Cable
- No changes.
Active Storage
-
Add structured events for Active Storage:
active_storage.service_uploadactive_storage.service_downloadactive_storage.service_streaming_downloadactive_storage.previewactive_storage.service_deleteactive_storage.service_delete_prefixedactive_storage.service_existactive_storage.service_urlactive_storage.service_mirror
Gannon McGibbon
-
Allow analyzers and variant transformer to be fully configurable
# ActiveStorage.analyzers can be set to an empty array: config.active_storage.analyzers = [] # => ActiveStorage.analyzers = [] # or use custom analyzer: config.active_storage.analyzers = [ CustomAnalyzer ] # => ActiveStorage.analyzers = [ CustomAnalyzer ]
If no configuration is provided, it will use the default analyzers.
You can also disable variant processor to remove warnings on startup about missing gems.
config.active_storage.variant_processor = :disabled
zzak, Alexandre Ruban
Action Mailbox
- No changes.
Action Text
-
De-couple
@rails/actiontext/attachment_upload.jsfromTrix.AttachmentImplement
@rails/actiontext/index.jswith adirect-upload:progressevent
listeners andPromiseresolution.Sean Doyle
-
Capture block content for form helper methods
<%= rich_textarea_tag :content, nil do %> <h1>hello world</h1> <% end %> <!-- <input type="hidden" name="content" id="trix_input_1" value="<h1>hello world</h1>"/><trix-editor … --> <%= rich_textarea :message, :content, input: "trix_input_1" do %> <h1>hello world</h1> <% end %> <!-- <input type="hidden" name="message[content]" id="trix_input_1" value="<h1>hello world</h1>"/><trix-editor … --> <%= form_with model: Message.new do |form| %> <%= form.rich_textarea :content do %> <h1>hello world</h1> <% end %> <% end %> <!-- <form action="/messages" accept-charset="UTF-8" method="post"><input type="hidden" name="message[content]" id="message_content_trix_input_message" value="<h1>hello world</h1>"/><trix-editor … -->
Sean Doyle
-
Generalize
:rich_text_areaCapybara selectorPrepare for more Action Text-capable WYSIWYG editors by making
:rich_text_arearely on the presence of[role="textbox"]and
[contenteditable]HTML attributes rather than a<trix-editor>element.Sean Doyle
Railties
-
Suggest
bin/rails action_text:installfrom Action Dispatch error pageSean Doyle
-
Remove deprecated
STATS_DIRECTORIES.Rafael Mendonça França
-
Remove deprecated
bin/rake statscommand.Rafael Mendonça França
-
Remove deprecated
rails/console/methods.rbfile.Rafael Mendonça França
-
Don't generate system tests by default.
Rails scaffold generator will no longer generate system tests by default. To enable this pass
--system-tests=trueor generate them withbin/rails generate system_test name_of_test.Eileen M. Uchitelle
-
Optionally skip bundler-audit.
Skips adding the
bin/bundler-audit&config/bundler-audit.ymlif the gem is not installed whenbin/rails app:updateruns.Passes an option to
--skip-bundler-auditwhen new apps are generated & adds that same option to the--minimalgenerator flag.Jill Klang
-
Show engine routes in
/rails/info/routesas well.Petrik de Heus
-
Exclude
asset_pathconfiguration from Kamaldeploy.ymlfor API applications.API applications don't serve assets, so the
asset_pathconfiguration indeploy.yml
is not needed and can cause 404 errors on in-flight requests. The asset_path is now
only included for regular Rails applications that serve assets.Saiqul Haq
-
Reverted the incorrect default
config.public_file_server.headersconfig.If you created a new application using Rails
8.1.0.beta1, make sure to regenerate
config/environments/production.rb, or to manually edit theconfig.public_file_server.headers
configuration to just be:# Cache assets for far-future expiry since they are all digest stamped. config.public_file_server.headers = { "cache-control" => "public, max-age=#{1.year.to_i}" }
Jean Boussier
Guides
- No changes.