Releases: rails/rails
8.1.1
Active Support
- No changes.
Active Model
- No changes.
Active Record
- No changes.
Action View
-
Respect
remove_hidden_field_autocompleteconfig in form builderhidden_field.Rafael Mendonça França
Action Pack
-
Allow methods starting with underscore to be action methods.
Disallowing methods starting with an underscore from being action methods
was an unintended side effect of the performance optimization in
207a254.Fixes #55985.
Rafael Mendonça França
Active Job
-
Only index new serializers.
Jesse Sharps
Action Mailer
- No changes.
Action Cable
- No changes.
Active Storage
- No changes.
Action Mailbox
- No changes.
Action Text
- No changes.
Railties
-
Do not assume and force SSL in production by default when using Kamal, to allow for out of the box Kamal deployments.
It is still recommended to assume and force SSL in production as soon as you can.
Jerome Dalbert
Guides
- No changes.
8.0.4
Active Support
-
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
-
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
Active Model
- No changes.
Active Record
-
Fix SQLite3 data loss during table alterations with CASCADE foreign keys.
When altering a table in SQLite3 that is referenced by child tables with
ON DELETE CASCADEforeign keys, ActiveRecord would silently delete all
data from the child tables. This occurred because SQLite requires table
recreation for schema changes, and during this process the original table
is temporarily dropped, triggering CASCADE deletes on child tables.The root cause was incorrect ordering of operations. The original code
wrappeddisable_referential_integrityinside a transaction, but
PRAGMA foreign_keyscannot be modified inside a transaction in SQLite -
attempting to do so simply has no effect. This meant foreign keys remained
enabled during table recreation, causing CASCADE deletes to fire.The fix reverses the order to follow the official SQLite 12-step ALTER TABLE
procedure:disable_referential_integritynow wraps the transaction instead
of being wrapped by it. This ensures foreign keys are properly disabled
before the transaction starts and re-enabled after it commits, preventing
CASCADE deletes while maintaining data integrity through atomic transactions.Ruy Rocha
-
Add support for bound SQL literals in CTEs.
Nicolas Bachschmidt
-
Fix
belongs_toassociations not to clear the entire composite primary key.When clearing a
belongs_toassociation that references a model with composite primary key,
only the optional part of the key should be cleared.zzak
-
Fix invalid records being autosaved when distantly associated records are marked for deletion.
Ian Terrell, axlekb AB
Action View
-
Restore
add_default_name_and_idmethod.Hartley McGuire
Action Pack
-
Submit test requests using
as: :htmlwithContent-Type: x-www-form-urlencodedSean Doyle
Active Job
- No changes.
Action Mailer
- No changes.
Action Cable
- No changes.
Active Storage
- No changes.
Action Mailbox
- No changes.
Action Text
- No changes.
Railties
- No changes.
Guides
- No changes.
7.2.3
Active Support
-
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
-
ActiveSupport::FileUpdateCheckerdoes not depend onTime.nowto prevent unnecessary reloads with time travel test helpersJan Grodowski
-
Fix
ActiveSupport::BroadcastLoggerfrom executing a block argument for each logger (tagged, info, etc.).Jared Armstrong
-
Fix
ActiveSupport::HashWithIndifferentAccess#transform_keys!removing defaults.Hartley McGuire
-
Fix
ActiveSupport::HashWithIndifferentAccess#tranform_keys!to handle collisions.If the transformation would result in a key equal to another not yet transformed one,
it would result in keys being lost.Before:
>> {a: 1, b: 2}.with_indifferent_access.transform_keys!(&:succ) => {"c" => 1}
After:
>> {a: 1, b: 2}.with_indifferent_access.transform_keys!(&:succ) => {"c" => 1, "d" => 2}
Jason T Johnson, Jean Boussier
-
Fix
ActiveSupport::Cache::MemCacheStore#read_multito handle network errors.This method specifically wasn't handling network errors like other codepaths.
Alessandro Dal Grande
-
Fix Active Support Cache
fetch_multiwhen local store is active.fetch_multinow properly yield to the provided block for missing entries
that have been recorded as such in the local store.Jean Boussier
-
Fix execution wrapping to report all exceptions, including
Exception.If a more serious error like
SystemStackErrororNoMemoryErrorhappens,
the error reporter should be able to report these kinds of exceptions.Gannon McGibbon
-
Fix
RedisCacheStoreandMemCacheStoreto also handle connection pool related errors.These errors are rescued and reported to
Rails.error.Jean Boussier
-
Fix
ActiveSupport::Cache#read_multito respect version expiry when using local cache.zzak
-
Fix
ActiveSupport::MessageVerifierandActiveSupport::MessageEncryptorconfiguration ofon_rotationcallback.verifier.rotate(old_secret).on_rotation { ... }
Now both work as documented.
Jean Boussier
-
Fix
ActiveSupport::MessageVerifierto always be able to verify both URL-safe and URL-unsafe payloads.This is to allow transitioning seemlessly from either configuration without immediately invalidating
all previously generated signed messages.Jean Boussier, Florent Beaurain, Ali Sepehri
-
Fix
cache.fetchto honor the provided expiry when:race_condition_ttlis used.cache.fetch("key", expires_in: 1.hour, race_condition_ttl: 5.second) do "something" end
In the above example, the final cache entry would have a 10 seconds TTL instead
of the requested 1 hour.Dhia
-
Better handle procs with splat arguments in
set_callback.Radamés Roriz
-
Fix
String#mb_charsto not mutate the receiver.Previously it would call
force_encodingon the receiver,
now it dups the receiver first.Jean Boussier
-
Improve
ErrorSubscriberto also mark error causes as reported.This avoid some cases of errors being reported twice, notably in views because of how
errors are wrapped inActionView::Template::Error.Jean Boussier
-
Fix
Module#module_parent_nameto return the correct name after the module has been named.When called on an anonymous module, the return value wouldn't change after the module was given a name
later by being assigned to a constant.mod = Module.new mod.module_parent_name # => "Object" MyModule::Something = mod mod.module_parent_name # => "MyModule"
Jean Boussier
-
Fix a bug in
ERB::Util.tokenizethat causes incorrect tokenization when ERB tags are preceeded by multibyte characters.Martin Emde
Active Model
-
Fix
has_secure_passwordto perform confirmation validation of the password even when blank.The validation was incorrectly skipped when the password only contained whitespace characters.
Fabio Sangiovanni
-
Handle missing attributes for
ActiveModel::Translation#human_attribute_name.zzak
-
Fix
ActiveModel::AttributeAssignment#assign_attributesto accept objects withouteach.Kouhei Yanagita
Active Record
-
Fix SQLite3 data loss during table alterations with CASCADE foreign keys.
When altering a table in SQLite3 that is referenced by child tables with
ON DELETE CASCADEforeign keys, ActiveRecord would silently delete all
data from the child tables. This occurred because SQLite requires table
recreation for schema changes, and during this process the original table
is temporarily dropped, triggering CASCADE deletes on child tables.The root cause was incorrect ordering of operations. The original code
wrappeddisable_referential_integrityinside a transaction, but
PRAGMA foreign_keyscannot be modified inside a transaction in SQLite -
attempting to do so simply has no effect. This meant foreign keys remained
enabled during table recreation, causing CASCADE deletes to fire.The fix reverses the order to follow the official SQLite 12-step ALTER TABLE
procedure:disable_referential_integritynow wraps the transaction instead
of being wrapped by it. This ensures foreign keys are properly disabled
before the transaction starts and re-enabled after it commits, preventing
CASCADE deletes while maintaining data integrity through atomic transactions.Ruy Rocha
-
Fix
belongs_toassociations not to clear the entire composite primary key.When clearing a
belongs_toassociation that references a model with composite primary key,
only the optional part of the key should be cleared.zzak
-
Fix invalid records being autosaved when distantly associated records are marked for deletion.
Ian Terrell, axlekb AB
-
Prevent persisting invalid record.
Edouard Chin
-
Fix count with group by qualified name on loaded relation.
Ryuta Kamizono
-
Fix
sumwith qualified name on loaded relation.Chris Gunther
-
Fix prepared statements on mysql2 adapter.
Jean Boussier
-
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
-
Don't add
id_valueattribute alias when attribute/column with that name already exists.Rob Lewis
-
Fix false positive change detection involving STI and polymorhic has one relationships.
Polymorphic
has_onerelationships would always be considered changed when defined in a STI child
class, causing nedless extra autosaves.David Fritsch
-
Fix stale associaton detection for polymophic
belong_to.Florent Beaurain, Thomas Crambert
-
Fix removal of PostgreSQL version comments in
structure.sqlfor latest PostgreSQL versions which include\restrict.Brendan Weibrecht
-
Fix
#mergewith#oror#andand a mixture of attributes and SQL strings resulting in an incorrect query.base = Comment.joins(:post).where(user_id: 1).where("recent = 1") puts base.merge(base.where(draft: true).or(Post.where(archived: true))).to_sql
Before:
SELECT "comments".* FROM "comments" INNER JOIN "posts" ON "posts"."id" = "comments"."post_id" WHERE (recent = 1) AND ( "comments"."user_id" = 1 AND (recent = 1) AND "comments"."draft" = 1 OR "posts"."archived" = 1 )
After:
SELECT "comments".* FROM "comments" INNER JOIN "posts" ON "posts"."id" = "comments"."post_id" WHERE "comments"."user_id" = 1 AND (recent = 1) AND ( "comments"."user_id" = 1 AND (recent = 1) AND "comments"."draft" = 1 OR "posts"."archived" = 1 )
Joshua Young
-
Fix inline
has_and_belongs_to_manyfixtures for tables with composite primary keys.fatkodima
-
Fix
annotatecomments to propagate toupdate_all/delete_all.fatkodima
-
Fix checking whether an unpersisted record is
include?d in a strictly
loadedhas_and_belongs_to_manyassociation.Hartley McGuire
-
Fix inline has_and_belongs_to_many fixtures for tables with composite primary keys.
fatkodima
-
create_or_find_bywill now correctly rollback a transaction.When using
create_or_find_by, raising a ActiveRecord::Rollback error
in aafter_savecallback had no effect, the transaction was committed
and a record created.Edouard Chin
-
Gracefully handle
Timeout.timeoutfiring during connection configuration.Use of
Timeout.timeoutcould result in improperly initialized database connection.This could lead to a partially configured connection being used, resulting in various exceptions,
the most common being with the PostgreSQLAdapter raisingundefined method 'key?' for nil
orTypeError: wrong argument type nil (expected PG::TypeMap).
...
7.1.6
Active Support
- No changes.
Active Model
- No changes.
Active Record
-
Gracefully handle
Timeout.timeoutfiring during connection configuration.Use of
Timeout.timeoutcould result in improperly initialized database connection.This could lead to a partially configured connection being used, resulting in various exceptions,
the most common being with the PostgreSQLAdapter raisingundefined methodkey?' for nilorTypeError: wrong argument type nil (expected PG::TypeMap)`.Jean Boussier
-
Fix error handling during connection configuration.
Active Record wasn't properly handling errors during the connection configuration phase.
This could lead to a partially configured connection being used, resulting in various exceptions,
the most common being with the PostgreSQLAdapter raisingundefined methodkey?' for nilorTypeError: wrong argument type nil (expected PG::TypeMap)`.Jean Boussier
-
Fix prepared statements on mysql2 adapter.
Jean Boussier
-
Fix a race condition in
ActiveRecord::Base#method_missingwhen lazily defining attributes.If multiple thread were concurrently triggering attribute definition on the same model,
it could result in aNoMethodErrorbeing raised.Jean Boussier
Action View
- No changes.
Action Pack
- No changes.
Active Job
- No changes.
Action Mailer
- No changes.
Action Cable
-
Fixed compatibility with
redisgem5.4.1Jean Boussier
Active Storage
- No changes.
Action Mailbox
- No changes.
Action Text
- No changes.
Railties
- No changes.
Guides
- No changes.
7.0.10
See https://github.com/rails/rails/releases/tag/v7.0.9 for information about this release.
7.0.9
Active Support
-
Fix
ActiveSupport::Notifications.publish_eventto preserve units.This solves the incorrect reporting of time spent running Active Record
asynchronous queries (by a factor1000).Jean Boussier
-
Fix ActiveSupport::Deprecation to handle blaming generated code
Jean Boussier, fatkodima
-
Fix
#to_fs(:human_size)to correctly work with negative numbers.Earlopain
-
Add
bigdecimalas Active Support dependency that is a bundled gem candidate for Ruby 3.4.bigdecimal3.1.4 or higher version will be installed.
Ruby 2.7 and 3.0 users who wantbigdecimalversion 2.0.0 or 3.0.0 behavior as a default gem,
pin thebigdecimalversion in your application Gemfile.Koichi ITO
-
Ensure
{down,up}case_firstreturns non-frozen string.Jonathan Hefner
-
Add
drb,mutex_mandbase64that are bundled gem candidates for Ruby 3.4Yasuo Honda
-
Fix
delete_matchedfor file cache store to work with keys longer than the
max filename size.fatkodima and Jonathan Hefner
-
Fix MemoryStore to prevent race conditions when incrementing or decrementing.
Pierre Jambet
-
Fix MemoryStore to preserve entries TTL when incrementing or decrementing
This is to be more consistent with how MemCachedStore and RedisCacheStore behaves.
Jean Boussier
-
NumberHelper: handle objects responding to_d.
fatkodima
-
NumberHelper: handle very large numbers.
Alex Ghiculescu, fatkodima
-
Fix Range#overlaps? not taking empty ranges into account on Ruby < 3.3
Nobuyoshi Nakada, Shouichi Kamiya, Hartley McGuire
Active Model
- No changes.
Active Record
-
Fix an issue that could cause database connection leaks
If Active Record successfully connected to the database, but then failed
to read the server informations, the connection would be leaked until the
Ruby garbage collector triggers.Jean Boussier
-
Fix single quote escapes on default generated MySQL columns
MySQL 5.7.5+ supports generated columns, which can be used to create a column that is computed from an expression.
Previously, the schema dump would output a string with double escapes for generated columns with single quotes in the default expression.
This would result in issues when importing the schema on a fresh instance of a MySQL database.
Now, the string will not be escaped and will be valid Ruby upon importing of the schema.
Yash Kapadia
-
Fix
Relation#transactionto not apply a default scopeThe method was incorrectly setting a default scope around its block:
Post.where(published: true).transaction do Post.count # SELECT COUNT(*) FROM posts WHERE published = FALSE; end
Jean Boussier
-
Fix renaming primary key index when renaming a table with a UUID primary key
in PostgreSQL.fatkodima
-
Fix
where(field: values)queries whenfieldis a serialized attribute
(for example, whenfieldusesActiveRecord::Base.serializeor is a JSON
column).João Alves
-
Don't mark Float::INFINITY as changed when reassigning it
When saving a record with a float infinite value, it shouldn't mark as changed
Maicol Bentancor
-
ActiveRecord::Base.table_namenow returnsnilinstead of raising
"undefined methodabstract_class?for Object:Class".a5-stable
-
Fix upserting for custom
:on_duplicateand:unique_byconsisting of all
inserts keys.fatkodima
-
Fix
NoMethodErrorwhen casting a PostgreSQLmoneyvalue that uses a
comma as its radix point and has no leading currency symbol. For example,
when casting"3,50".Andreas Reischuck and Jonathan Hefner
-
Fix duplicate quoting for check constraint expressions in schema dump when using MySQL
A check constraint with an expression, that already contains quotes, lead to an invalid schema
dump with the mysql2 adapter.Fixes #42424.
Felix Tscheulin
-
Fix MySQL expression index dumping with escaped quotes.
fatkodima
-
Fix uniqueness validation on association not using overridden primary key.
fatkodima
Action View
-
Fix the
number_to_human_sizeview helper to correctly work with negative numbers.Earlopain
Action Pack
-
Fix
ActionDispatch::Executormiddleware to report errors handled byActionDispatch::ShowExceptions.In the default production environment,
ShowExceptionsrescue uncaught errors
and returns a response. Because if this the executor wouldn't report production
errors with the default Rails configuration.Jean Boussier
-
Add
raccas a dependency since it will become a bundled gem in Ruby 3.4.0Hartley McGuire
Active Job
-
Preserve the serialized timezone when deserializing
ActiveSupport::TimeWithZonearguments.Joshua Young
Action Mailer
- No changes.
Action Cable
- No changes.
Active Storage
-
Fix
ActiveStorage::Representations::ProxyControllernot returning the proper
preview image variant for previewable files.Chedli Bourguiba
-
Make untracked variants obey
config.active_storage.content_types_to_serve_as_binary
andconfig.active_storage.content_types_allowed_inline.Chedli Bourguiba and Jonathan Hefner
-
Fix direct upload forms when submit button contains nested elements.
Marc Köhlbrugge
-
Prevent
ActiveRecord::StrictLoadingViolationErrorwhen strict loading is
enabled and the variant of an Active Storage preview has already been
processed (for example, by callingActiveStorage::Preview#url).Jonathan Hefner
-
Fix variants not included when eager loading multiple records containing a single attachment
When using the
with_attached_#{name}scope for ahas_one_attachedrelation,
attachment variants were not eagerly loaded.Russell Porter
Action Mailbox
- No changes.
Action Text
- No changes.
Railties
- No changes.
Guides
- No changes.
8.1.0
Active 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
-
Add
ActiveSupport::Cache::Store#namespace=and#namespace.Can be used as an alternative to
Store#clearin some situations such as parallel
testing.Nick Schwaderer
-
Create
parallel_worker_idhelper for running parallel tests. This allows users to
know which worker they are currently running in.Nick Schwaderer
-
Make the cache of
ActiveSupport::Cache::Strategy::LocalCache::Middlewareupdatable.If the cache client at
Rails.cacheof a booted application changes, the corresponding
mounted middleware needs to update in order for request-local caches to be setup properly.
Otherwise, redundant cache operations will erroneously hit the datastore.Gannon McGibbon
-
Add
assert_events_reportedtest helper forActiveSupport::EventReporter.This new assertion allows testing multiple events in a single block, regardless of order:
assert_events_reported([ { name: "user.created", payload: { id: 123 } }, { name: "email.sent", payload: { to: "[email protected]" } } ]) do create_user_and_send_welcome_email end
George Ma
-
Add
ActiveSupport::TimeZone#standard_namemethod.zone = ActiveSupport::TimeZone['Hawaii'] # Old way ActiveSupport::TimeZone::MAPPING[zone.name] # New way zone.standard_name # => 'Pacific/Honolulu'
Bogdan Gusiev
-
Add Structured Event Reporter, accessible via
Rails.event.The Event Reporter provides a unified interface for producing structured events in Rails
applications:Rails.event.notify("user.signup", user_id: 123, email: "[email protected]")
It supports adding tags to events:
Rails.event.tagged("graphql") do # Event includes tags: { graphql: true } Rails.event.notify("user.signup", user_id: 123, email: "[email protected]") end
As well as context:
# All events will contain context: {request_id: "abc123", shop_id: 456} Rails.event.set_context(request_id: "abc123", shop_id: 456)
Events are emitted to subscribers. Applications register subscribers to
control how events are serialized and emitted. Subscribers must implement
an#emitmethod, which receives the event hash:class LogSubscriber def emit(event) payload = event[:payload].map { |key, value| "#{key}=#{value}" }.join(" ") source_location = event[:source_location] log = "[#{event[:name]}] #{payload} at #{source_location[:filepath]}:#{source_location[:lineno]}" Rails.logger.info(log) end end
Adrianna Chang
-
Make
ActiveSupport::Logger#freeze-friendly.Joshua Young
-
Make
ActiveSupport::Gzip.compressdeterministic based on input.ActiveSupport::Gzip.compressused to include a timestamp in the output,
causing consecutive calls with the same input data to have different output
if called during different seconds. It now always sets the timestamp to0
so that the output is identical for any given input.Rob Brackett
-
Given an array of
Thread::Backtrace::Locationobjects, the new method
ActiveSupport::BacktraceCleaner#clean_locationsreturns an array with the
clean ones:clean_locations = backtrace_cleaner.clean_locations(caller_locations)
Filters and silencers receive strings as usual. However, the
path
attributes of the locations in the returned array are the original,
unfiltered ones, since locations are immutable.Xavier Noria
-
Improve
CurrentAttributesandExecutionContextstate managment in test cases.Previously these two global state would be entirely cleared out whenever calling
into code that is wrapped by the Rails executor, typically Action Controller or
Active Job helpers:test "#index works" do CurrentUser.id = 42 get :index CurrentUser.id == nil end
Now re-entering the executor properly save and restore that state.
Jean Boussier
-
The new method
ActiveSupport::BacktraceCleaner#first_clean_location
returns the first clean location of the caller's call stack, ornil.
Locations areThread::Backtrace::Locationobjects. Useful when you want to
report the application-level location where something happened as an object.Xavier Noria
-
FileUpdateChecker and EventedFileUpdateChecker ignore changes in Gem.path now.
Ermolaev Andrey, zzak
-
The new method
ActiveSupport::BacktraceCleaner#first_clean_framereturns
the first clean frame of the caller's backtrace, ornil. Useful when you
want to report the application-level frame where something happened as a
string.Xavier Noria
-
Always clear
CurrentAttributesinstances.Previously
CurrentAttributesinstance would be reset at the end of requests.
Meaning its attributes would be re-initialized.This is problematic because it assume these objects don't hold any state
other than their declared attribute, which isn't always the case, and
can lead to state leak across request.Now
CurrentAttributesinstances are abandoned at the end of a request,
and a new instance is created at the start of the next request.Jean Boussier, Janko Marohnić
-
Add public API for
before_fork_hookin parallel testing.Introduces a public API for calling the before fork hooks implemented by parallel testing.
parallelize_before_fork do # perform an action before test processes are forked end
Eileen M. Uchitelle
-
Implement ability to skip creating parallel testing databases.
With parallel testing, Rails will create a database per process. If this isn't
desirable or you would like to implement databases handling on your own, you can
now turn off this default behavior.To skip creating a database per process, you can change it via the
parallelizemethod:parallelize(workers: 10, parallelize_databases: false)
or via the application configuration:
config.active_support.parallelize_databases = false
Eileen M. Uchitelle
-
Allow to configure maximum cache key sizes
When the key exceeds the configured limit (250 bytes by default), it will be truncated and
the di...
8.1.0.rc1
Active 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.o...
8.0.3
Active Support
-
ActiveSupport::FileUpdateCheckerdoes not depend onTime.nowto prevent unnecessary reloads with time travel test helpersJan Grodowski
-
Fix
ActiveSupport::BroadcastLoggerfrom executing a block argument for each logger (tagged, info, etc.).Jared Armstrong
-
Make
ActiveSupport::Logger#freeze-friendly.Joshua Young
-
Fix
ActiveSupport::HashWithIndifferentAccess#transform_keys!removing defaults.Hartley McGuire
-
Fix
ActiveSupport::HashWithIndifferentAccess#tranform_keys!to handle collisions.If the transformation would result in a key equal to another not yet transformed one,
it would result in keys being lost.Before:
>> {a: 1, b: 2}.with_indifferent_access.transform_keys!(&:succ) => {"c" => 1}
After:
>> {a: 1, b: 2}.with_indifferent_access.transform_keys!(&:succ) => {"c" => 1, "d" => 2}
Jason T Johnson, Jean Boussier
-
Fix
ActiveSupport::Cache::MemCacheStore#read_multito handle network errors.This method specifically wasn't handling network errors like other codepaths.
Alessandro Dal Grande
-
Fix configuring
RedisCacheStorewithraw: true.fatkodima
-
Fix
Enumerable#solefor infinite collections.fatkodima
Active Model
-
Fix
has_secure_passwordto perform confirmation validation of the password even when blank.The validation was incorrectly skipped when the password only contained whitespace characters.
Fabio Sangiovanni
Active Record
-
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
-
Don't add
id_valueattribute alias when attribute/column with that name already exists.Rob Lewis
-
Fix false positive change detection involving STI and polymorphic has one relationships.
Polymorphic
has_onerelationships would always be considered changed when defined in a STI child
class, causing nedless extra autosaves.David Fritsch
-
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
-
Fix stale association detection for polymorphic
belongs_to.Florent Beaurain, Thomas Crambert
-
Fix removal of PostgreSQL version comments in
structure.sqlfor latest PostgreSQL versions which include\restrictBrendan Weibrecht
-
Allow setting
schema_formatin database configuration.primary: schema_format: rubyUseful in multi-database setups to have different formats per-database.
T S Vallender
-
Use ntuples to populate row_count instead of count for Postgres
Jonathan Calvert
-
Fix
#mergewith#oror#andand a mixture of attributes and SQL strings resulting in an incorrect query.base = Comment.joins(:post).where(user_id: 1).where("recent = 1") puts base.merge(base.where(draft: true).or(Post.where(archived: true))).to_sql
Before:
SELECT "comments".* FROM "comments" INNER JOIN "posts" ON "posts"."id" = "comments"."post_id" WHERE (recent = 1) AND ( "comments"."user_id" = 1 AND (recent = 1) AND "comments"."draft" = 1 OR "posts"."archived" = 1 )
After:
SELECT "comments".* FROM "comments" INNER JOIN "posts" ON "posts"."id" = "comments"."post_id" WHERE "comments"."user_id" = 1 AND (recent = 1) AND ( "comments"."user_id" = 1 AND (recent = 1) AND "comments"."draft" = 1 OR "posts"."archived" = 1 )
Joshua Young
-
Fix inline
has_and_belongs_to_manyfixtures for tables with composite primary keys.fatkodima
-
Fix migration log message for down operations.
Bernardo Barreto
-
Prepend
extra_flagsin postgres'structure_loadWhen specifying
structure_load_flagswith a postgres adapter, the flags
were appended to the default flags, instead of prepended.
This caused issues with flags not being taken into account by postgres.Alice Loeser
-
Fix
annotatecomments to propagate toupdate_all/delete_all.fatkodima
-
Fix checking whether an unpersisted record is
include?d in a strictly
loadedhas_and_belongs_to_manyassociation.Hartley McGuire
-
create_or_find_bywill now correctly rollback a transaction.When using
create_or_find_by, raising a ActiveRecord::Rollback error
in aafter_savecallback had no effect, the transaction was committed
and a record created.Edouard Chin
-
Gracefully handle
Timeout.timeoutfiring during connection configuration.Use of
Timeout.timeoutcould result in improperly initialized database connection.This could lead to a partially configured connection being used, resulting in various exceptions,
the most common being with the PostgreSQLAdapter raisingundefined method 'key?' for nil
orTypeError: wrong argument type nil (expected PG::TypeMap).Jean Boussier
-
Fix stale state for composite foreign keys in belongs_to associations.
Varun Sharma
Action View
-
Fix label with
foroption not getting prefixed by formnamespacevalueAbeid Ahmed, Hartley McGuire
-
Fix
javascript_include_tagtypeoption to accept either strings and symbols.javascript_include_tag "application", type: :module javascript_include_tag "application", type: "module"
Previously, only the string value was recognized.
Jean Boussier
-
Fix
excerpthelper with non-whitespace separator.Jonathan Hefner
Action Pack
-
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
-
Fix
Rails.application.reload_routes!from clearing almost all routes.When calling
Rails.application.reload_routes!inside a middleware of
a Rake task, it was possible under certain conditions that all routes would be cleared.
If ran inside a middleware, this would result in getting a 404 on most page you visit.
This issue was only happening in development.Edouard Chin
-
Address
rack 3.2deprecations warnings.warning: Status code :unprocessable_entity is deprecated and will be removed in a future version of Rack. Please use :unprocessable_content instead.Rails API will transparently convert one into the other for the foreseeable future.
Earlopain, Jean Boussier
-
Support hash-source in Content Security Policy.
madogiwa
-
Always return empty body for HEAD requests in
PublicExceptionsand
DebugExceptions.This is required by
Rack::Lint(per RFC9110).Hartley McGuire
Active Job
-
Include the actual Active Job locale when serializing rather than I18n locale.
Adrien S
-
Fix
retry_jobinstrumentation when using:testadapter for Active Job.fatkodima
Action Mailer
- No changes.
Action Cable
-
Fixed compatibility with
redisgem5.4.1Jean Boussier
-
Fixed a possible race condition in
stream_from.OuYangJinTing
Active Storage
-
Address deprecation of
Aws::S3::Object#upload_streaminActiveStorage::Service::S3Service.Joshua Young
-
Fix
config.active_storage.touch_attachment_recordsto work with eager loading.fatkodima
Action Mailbox
- No changes.
Action Text
-
Add rollup-plugin-terser as a dev dependency.
Édouard Chin
Railties
-
Fix
polymorphic_urlandpolymorphic_pathnot working when routes are not loaded.Édouard Chin
-
Fix Rails console to not override user defined IRB_NAME.
Only change the prompt name if it hasn't been customized in
.irbrc.Jarrett Lusso
Guides
- No changes.
8.1.0.beta1
Active Support
-
Add
ActiveSupport::Cache::Store#namespace=and#namespace.Can be used as an alternative to
Store#clearin some situations such as parallel
testing.Nick Schwaderer
-
Create
parallel_worker_idhelper for running parallel tests. This allows users to
know which worker they are currently running in.Nick Schwaderer
-
Make the cache of
ActiveSupport::Cache::Strategy::LocalCache::Middlewareupdatable.If the cache client at
Rails.cacheof a booted application changes, the corresponding
mounted middleware needs to update in order for request-local caches to be setup properly.
Otherwise, redundant cache operations will erroneously hit the datastore.Gannon McGibbon
-
Add
assert_events_reportedtest helper forActiveSupport::EventReporter.This new assertion allows testing multiple events in a single block, regardless of order:
assert_events_reported([ { name: "user.created", payload: { id: 123 } }, { name: "email.sent", payload: { to: "[email protected]" } } ]) do create_user_and_send_welcome_email end
George Ma
-
Add
ActiveSupport::TimeZone#standard_namemethod.zone = ActiveSupport::TimeZone['Hawaii'] # Old way ActiveSupport::TimeZone::MAPPING[zone.name] # New way zone.standard_name # => 'Pacific/Honolulu'
Bogdan Gusiev
-
Add Structured Event Reporter, accessible via
Rails.event.The Event Reporter provides a unified interface for producing structured events in Rails
applications:Rails.event.notify("user.signup", user_id: 123, email: "[email protected]")
It supports adding tags to events:
Rails.event.tagged("graphql") do # Event includes tags: { graphql: true } Rails.event.notify("user.signup", user_id: 123, email: "[email protected]") end
As well as context:
# All events will contain context: {request_id: "abc123", shop_id: 456} Rails.event.set_context(request_id: "abc123", shop_id: 456)
Events are emitted to subscribers. Applications register subscribers to
control how events are serialized and emitted. Subscribers must implement
an#emitmethod, which receives the event hash:class LogSubscriber def emit(event) payload = event[:payload].map { |key, value| "#{key}=#{value}" }.join(" ") source_location = event[:source_location] log = "[#{event[:name]}] #{payload} at #{source_location[:filepath]}:#{source_location[:lineno]}" Rails.logger.info(log) end end
Adrianna Chang
-
Make
ActiveSupport::Logger#freeze-friendly.Joshua Young
-
Make
ActiveSupport::Gzip.compressdeterministic based on input.ActiveSupport::Gzip.compressused to include a timestamp in the output,
causing consecutive calls with the same input data to have different output
if called during different seconds. It now always sets the timestamp to0
so that the output is identical for any given input.Rob Brackett
-
Given an array of
Thread::Backtrace::Locationobjects, the new method
ActiveSupport::BacktraceCleaner#clean_locationsreturns an array with the
clean ones:clean_locations = backtrace_cleaner.clean_locations(caller_locations)
Filters and silencers receive strings as usual. However, the
path
attributes of the locations in the returned array are the original,
unfiltered ones, since locations are immutable.Xavier Noria
-
Improve
CurrentAttributesandExecutionContextstate managment in test cases.Previously these two global state would be entirely cleared out whenever calling
into code that is wrapped by the Rails executor, typically Action Controller or
Active Job helpers:test "#index works" do CurrentUser.id = 42 get :index CurrentUser.id == nil end
Now re-entering the executor properly save and restore that state.
Jean Boussier
-
The new method
ActiveSupport::BacktraceCleaner#first_clean_location
returns the first clean location of the caller's call stack, ornil.
Locations areThread::Backtrace::Locationobjects. Useful when you want to
report the application-level location where something happened as an object.Xavier Noria
-
FileUpdateChecker and EventedFileUpdateChecker ignore changes in Gem.path now.
Ermolaev Andrey, zzak
-
The new method
ActiveSupport::BacktraceCleaner#first_clean_framereturns
the first clean frame of the caller's backtrace, ornil. Useful when you
want to report the application-level frame where something happened as a
string.Xavier Noria
-
Always clear
CurrentAttributesinstances.Previously
CurrentAttributesinstance would be reset at the end of requests.
Meaning its attributes would be re-initialized.This is problematic because it assume these objects don't hold any state
other than their declared attribute, which isn't always the case, and
can lead to state leak across request.Now
CurrentAttributesinstances are abandoned at the end of a request,
and a new instance is created at the start of the next request.Jean Boussier, Janko Marohnić
-
Add public API for
before_fork_hookin parallel testing.Introduces a public API for calling the before fork hooks implemented by parallel testing.
parallelize_before_fork do # perform an action before test processes are forked end
Eileen M. Uchitelle
-
Implement ability to skip creating parallel testing databases.
With parallel testing, Rails will create a database per process. If this isn't
desirable or you would like to implement databases handling on your own, you can
now turn off this default behavior.To skip creating a database per process, you can change it via the
parallelizemethod:parallelize(workers: 10, parallelize_databases: false)
or via the application configuration:
config.active_support.parallelize_databases = false
Eileen M. Uchitelle
-
Allow to configure maximum cache key sizes
When the key exceeds the configured limit (250 bytes by default), it will be truncated and
the digest of the rest of the key appended to it.Note that previously
ActiveSupport::Cache::RedisCacheStoreallowed up to 1kb cache keys before
truncation, which is now reduced to 250 bytes.config.cache_store = :redis_cache_store, { max_key_size: 64 }
fatkodima
-
Use
UNLINKcommand instead ofDELinActiveSupport::Cache::RedisCacheStorefor non-blocking deletion.Aron Roh
-
Add
Cache#read_counterandCache#write_counterRails.cache.write_counter("foo", 1) Rails.cache.read_counter("foo") # => 1 Rails.cache.increment("foo") Rails.cache.read_counter("foo") # => 2
Alex Ghiculescu
-
Introduce ActiveSupport::Testing::ErrorReporterAssertions#capture_error_reports
Captures all reported errors from within the block that match the given
error class.reports = capture_error_reports(IOError) do Rails.error.report(IOError.new("Oops")) Rails.error.report(IOError.new("Oh no")) Rails.error.report(StandardError.new) end assert_equal 2, reports.size assert_equal "Oops", reports.first.error.message assert_equal "Oh no", reports.last.error.message
Andrew Novoselac
-
Introduce ActiveSupport::ErrorReporter#add_middleware
When reporting an error, the error context middleware will be called with the reported error
and base execution context. The stack may mutate the context hash. The mutated context will
then be passed to error subscribers. Middleware receives the same parameters asErrorReporter#report.Andrew Novoselac, Sam Schmidt
-
Change execution wrapping to report all exceptions, including
Exception.If a more serious error like
SystemStackErrororNoMemoryErrorhappens,
the error reporter should be able to report these kinds of exceptions.Gannon McGibbon
-
ActiveSupport::Testing::Parallelization.before_fork_hookallows declaration of callbacks that
are invoked immediately before forking test workers.Mike Dalessio
-
Allow the
#freeze_timetesting helper to accept a date or time argument.Time.current # => Sun, 09 Jul 2024 15:34:49 EST -05:00 freeze_time Time.current + 1.day sleep 1 Time.current # => Mon, 10 Jul 2024 15:34:49 EST -05:00
Joshua Young
-
ActiveSupport::JSONnow accepts optionsIt is now possible to pass options to
ActiveSupport::JSON:ActiveSupport::JSON.decode('{"key": "value"}', symbolize_names: true) # => { key: "value" }
matthaigh27
-
ActiveSupport::Testing::NotificationAssertions'sassert_notificationnow matches against payload subsets by default.Previously the following assertion would fail due to excess key vals in the notification payload. Now with payload subset matching, it will pass.
assert_notification("post.submitted", title: "Cool Post") do ActiveSupport::Notifications.instrument("post.submitted", title: "Cool Post", body: "Cool Body") end
Additionally, you can now persist a matched notification for more customized ass...