gems activerecord 8.1.4

latest release: 7.2.4
5 hours ago

Active Support

  • Fix the debug error page rendering for SyntaxErrors with multi-line messages.

    Marco Roth

  • Make ActiveSupport::JSON.decode compatible with the upcoming json 3.0 gem.

    Earlopain

  • Fix number_to_human_size crashing for sizes above a terabyte by supporting
    petabyte, exabyte, and zettabyte storage units.

    Kenta Ishizaki

  • Fix Range#sole raising NoMethodError when the enumerable core extension
    isn't already loaded.

    Kenta Ishizaki

  • Fix ActiveSupport::Cache::FileStore raising NameError for FileUtils
    when fileutils isn't already loaded.

    Kenta Ishizaki

  • Fix Enumerable#in_order_of with filter: true dropping nil elements
    explicitly named in the series.

    Kenta Ishizaki

  • Keep HashWithIndifferentAccess#filter returning a HashWithIndifferentAccess
    instead of a plain Hash.

    Kenta Ishizaki

  • Fix number_to_human and number_to_human_size crashing when :precision is nil.

    Kenta Ishizaki

  • Fix ActiveSupport::InheritableOptions#to_h to recursively flatten nested
    InheritableOptions parents.

    Andrew Novoselac

  • Fix ActiveSupport::StructuredEventSubscriber.debug_only leaking debug-only
    methods across subscriber subclasses.

    Kenta Ishizaki

  • Fix ActiveSupport::Inflector#transliterate mutating the caller's string.

    Kenta Ishizaki

  • Fix Hash.from_xml raising Date::Error on type="date" values surrounded
    by whitespace.

    Kenta Ishizaki

  • Fix Time#advance and DateTime#advance mutating the options hash passed
    by the caller.

    Kenta Ishizaki

  • Fix ActiveSupport::Cache::MemoryStore#cleanup raising NoMethodError when
    used with a non-DupCoder serializer.

    Kenta Ishizaki

  • Fix String#truncate with :separator misbehaving when the :omission is
    longer than the target length.

    Kenta Ishizaki

  • Fix ActiveSupport::Cache::Store#delete_multi mutating the names array passed
    by the caller.

    Kenta Ishizaki

  • Fix number_to_currency crashing on a negative number when :precision is nil.

    Kenta Ishizaki

  • Fix TimeZone#strptime with %s dropping the sub-second fraction of the timestamp.

    Kenta Ishizaki

  • Fix HashWithIndifferentAccess.new dropping a falsy (false or 0) default
    value from the source hash.

    Kenta Ishizaki

  • Fix Range#include? and Range#=== raising on exclusive non-integer sub-ranges.

    Kenta Ishizaki

  • Fix number_to_delimited corrupting numbers that begin with a + or - sign.

    Kenta Ishizaki

  • Fix ActiveSupport::InheritableOptions#== raising NoMethodError when compared
    with a non-Hash object.

    Kenta Ishizaki

  • Fix Enumerable#in_order_of with filter: false dropping elements whose keyed
    value is nil.

    Hammad Khan

  • Stop the DRb service when shutting down parallel test workers, preventing it
    from lingering after the test run.

    Shuta Mugikura

  • Preserve the encoding of ActiveSupport::SafeBuffer values round-tripped through
    ActiveSupport::MessagePack.

    Rafael Mendonça França

  • Fix number_to_phone without an area code stripping a leading delimiter when the
    number itself coincidentally starts with the delimiter string.

    Tahsin Hasan

  • Update ActiveSupport::TimeZone mappings to use the current IANA identifiers
    Europe/Kyiv (was Europe/Kiev) and Asia/Yangon (was Asia/Rangoon).

    tsymbalenkovlad

  • Use the faster string-based delimiter logic by default in number_to_delimited,
    instead of the regular expression fallback.

    Shinichi Maeshima

  • Preserve the requested key order in ActiveSupport::Cache::Store#fetch_multi
    when a local cache is active.

    Previously, if some keys were served from the local cache and others from the
    underlying store, fetch_multi returned the local cache hits first instead of
    following the order of the requested keys.

    Mueez Afzal

  • Fix String#parameterize raising TypeError when separator is nil.

    parameterize already treats a nil separator the same as an empty one when
    squeezing and trimming separators, but raised TypeError before reaching that
    point. A nil separator now behaves like "", removing the unwanted characters.

    "Donald E. Knuth".parameterize(separator: nil) # => "donaldeknuth"

    Hammad Khan

  • Add RedisClient::Error to ActiveSupport::Cache::RedisCacheStore's failsafe rescue list.

    The redis-rb gem normally translates RedisClient::* errors into Redis::* errors but in
    some rare cases, such as when using sentinels, RedisClient::* errors may slip through.

    David Arrunategui

  • Fix ActiveSupport::Duration#in_minutes, #in_hours, #in_days,
    #in_weeks, #in_months, and #in_years truncating sub-second precision.

    These methods divided the duration's integer second count (in_seconds,
    aliased to to_i) instead of its exact value, so any fractional second was
    silently dropped before the conversion.

    # Before
    90.5.seconds.in_minutes # => 1.5
    
    # After
    90.5.seconds.in_minutes # => 1.5083333333333333

    Kenta Ishizaki

  • Fix JSON encoding of non-String Hash keys.

    The old encoder would simply call to_s on them, the newer encoder
    would incorrectly call as_json instead.

    In the case of Time, DateTime and TimeWithZone this would result
    in different serialization of time keys: "2009-01-01T12:30:00.000Z" (arguably better)
    instead of "2009-01-01 12:30:00 UTC" (how it used to be).

    Kenta Ishizaki

  • Fix number_to_phone dropping only the first character of a
    multi-character :delimiter when no area code is present.

    The leading delimiter produced by an empty first capture group was
    stripped with slice!(0, 1), which assumed a single-character
    delimiter. Multi-character (and multibyte) delimiters now work:

    number_to_phone(5551234, delimiter: " - ")  # => "555 - 1234"
    # was "- 555 - 1234"
    

    Kenta Ishizaki

  • Fix titleize inflector to consider Unicode characters

    "ćasim đipa".titleize # => "Ćasim Đipa"

    Eldin Guzin

Active Model

  • Fix ActiveModel::Errors#import mutating the override options hash passed to it.

    Kenta Ishizaki

  • Fix normalizes not detecting in-place changes for attributes whose database
    cast type differs from the attribute type (e.g. JSON columns), causing
    normalization to be skipped on validation.

    Chedli Bourguiba

  • Fix alias_attribute accumulating duplicate entries in aliases_by_attribute_name
    when called multiple times with the same arguments.

    Nicholas Jakobsen

  • Fix normalizes re-applying normalizations on every validation of an
    unpersisted record, and speed up validation of normalized attributes.

    The in-place mutation check re-ran the normalizer on every valid? of an
    unpersisted record: wasteful for idempotent normalizers and compounded the
    result for non-idempotent ones. Normalizations are now re-applied only on a
    genuine in-place mutation.

    Yaroslav Markin

  • Limit the size of strings ActiveModel::Type::Integer will coerce with to_i.

    Calling to_i on very long strings can take a long time and could be used as
    a DoS vector. Integer casting now only considers the first _limit * 4 bytes
    of a string (16 bytes for a default 4-byte integer, 32 bytes for an 8-byte
    bigint), which is enough to hold the maximum representable value plus a sign
    or a short slug suffix.

    Aaron Patterson, Jean Boussier

Active Record

  • Avoid deadlocks when concurrent find_or_create_by calls read back the same
    record within MySQL transactions.

    Use a shared lock for the read after a duplicate insert, preserving visibility
    under REPEATABLE READ without upgrading competing shared locks to exclusive locks.
    This also applies to create_or_find_by and the bang variants of both methods.

    Fixes #54281.

    Kirsten Westeinde

  • Filter the database password out of failed db: task command error messages.

    Ngan Pham

  • Fix ActiveRecord::TypeCaster::Connection sometimes leaking a checked-out
    connection.

    Hartley McGuire

  • Fix PostgreSQL exclusion constraints with multiline expressions being parsed
    incorrectly during schema introspection.

    Jake McAllister

  • Fix async ActiveRecord::StatementCache#execute raising an error for
    out-of-range bind values instead of returning an empty result.

    viralpraxis

  • Fix where clauses with column-tuple syntax not resolving references to
    other tables.

    Chris Gunther

  • Fix distinct: true being ignored by average.

    Kenta Ishizaki

  • Fix belongs_to change tracking for composite foreign keys.

    Only the first foreign key column was checked for changes; now all foreign
    key columns are checked.

    Anas Khan

  • Make add_column(if_not_exists: true) reversible.

    Kenta Ishizaki

  • Quote the index name in MySQL enable_index and disable_index.

    Unquoted index names containing special characters could cause SQL syntax
    errors.

    Kenta Ishizaki

  • Make remove_foreign_key(if_exists: true) reversible.

    Kenta Ishizaki

  • Fix distinct: true being ignored by grouped sum.

    Kenta Ishizaki

  • Return an ActiveRecord::Promise from async_ids on a contradictory
    relation, instead of a plain ActiveRecord::Result.

    Kenta Ishizaki

  • Fix reversibility check for drop_virtual_table.

    The wrong argument was extracted, so the check for whether options were
    given could pass or fail incorrectly.

    Kenta Ishizaki

  • Fix remove_check_constraint(if_exists: true) incorrectly raising when
    removing by expression.

    The if_exists check did not pass the expression to
    check_constraint_exists?, so it could not find the constraint.

    Kenta Ishizaki

  • Clear PostgreSQL notices as they are handled, preventing warnings from
    leaking to subsequent queries.

    Matthew Draper

  • Fix WeakThreadKeyMap raising "can't add a new key into hash during
    iteration" when connections are checked in from multiple threads.

    Matthew Draper

  • Continue pool disconnect after a connection's cleanup or disconnect raises.

    Previously, a failure on one connection aborted the teardown, stranding
    remaining connections and their resources.

    Matthew Draper

  • Fix race condition between preconnect and the connection pool reaper.

    Yasuo Honda

  • Fix in_order_of raising when the column is a CTE reference.

    viralpraxis

  • Fix content_columns including composite primary key components.

    Only the first primary key column was excluded; now all primary key columns
    are excluded.

    Kenta Ishizaki

  • Treat remove_column with options but no type as irreversible.

    Previously, remove_column(:table, :column, default: nil) would not raise
    IrreversibleMigration because the options hash was mistaken for a column
    type.

    Kenta Ishizaki

  • Fix counter_cache_column crashing when :counter_cache is given as a
    Hash without a :column key.

    Kenta Ishizaki

  • Coerce seeds and use_metadata_table to booleans in UrlConfig.

    When configured via DATABASE_URL, these options were left as strings
    instead of being coerced to booleans like replica and database_tasks.

    Kenta Ishizaki

  • Fix excluding (and its without alias) to work with composite primary key
    models. Records passed to excluding are now matched by their full composite id
    instead of being looked up by a single primary key column.

    Kenta Ishizaki

  • Fix Relation#delete raising on a single composite primary key id.

    Model.delete(id) now wraps a single composite id in an array before building
    the WHERE clause, so a single record can be deleted by its composite id.

    Kenta Ishizaki

  • Fix reading a composite primary key after a partial select returning the
    raw value instead of nil for unselected key columns.

    The attribute defaults builder excluded only the single primary key column from
    defaults; for composite primary keys it left the unselected key columns in the
    defaults, so record.id returned an array of raw column values instead of
    [nil, nil]. All primary key columns are now excluded.

    Kenta Ishizaki

  • Fix find with an empty array on a composite primary key model returning the
    argument array instead of [].

    Model.find([]) now returns a fresh empty array for composite primary key
    models, matching single-key models.

    Kenta Ishizaki

  • Fix find with an order clause and an offset past the end of the ids raising
    RecordNotFound instead of returning an empty result.

    Kenta Ishizaki

  • Fix in_order_of dropping values that cannot be serialized for the column
    instead of turning them into an IS NULL match.

    Out-of-range integers and unknown enum keys are now ignored rather than
    silently matching rows with NULL in that column. When all requested values
    are unrepresentable, the relation returns no rows instead of building an empty
    CASE expression.

    Kenta Ishizaki

  • Fix stale finder_needs_type_condition? memo after the schema cache is reloaded.

    When an STI model's type column was removed and re-added (e.g. via a
    migration) and reset_column_information was called, the cached
    finder_needs_type_condition value was not cleared, so queries could omit the
    STI type condition. The memo is now reset on reload_schema_from_cache.

    Kenta Ishizaki

  • Fix PostgreSQL schema dump to qualify enum_type when the same enum name exists
    in different schemas.

    Previously the dumped enum_type used the bare type name, which could resolve to
    the wrong enum in another schema. It now uses the schema-qualified name.

    fatkodima

  • Fix PostgreSQL index introspection to parse opclasses from another schema.

    Index expressions using a schema-qualified opclass (e.g.
    USING gin(position test_schema.gin_trgm_ops)) are now parsed correctly so the
    opclass is captured without the schema prefix.

    Nicolas Vandenboegaerde

  • Fix belongs_to :touch with composite foreign keys.

    Touching the parent record when a belongs_to with a composite foreign key
    changes or is destroyed now correctly resolves the old and new parent by all
    foreign key columns.

    Romulo Storel

  • Fix add_index comment: option on a schema-qualified PostgreSQL table.

    The COMMENT ON INDEX statement now schema-qualifies the index name, so the
    comment is applied to the index in the correct schema instead of raising.

    Tobias Egli

  • Fix check_all_foreign_keys_valid! on PostgreSQL partitioned tables.

    The validation query previously matched constraints by name across all tables in
    the schema, marking unrelated constraints (including partition children) as not
    validated. It now scopes the update to the specific table.

    Alexis Andrieu

  • Revert stable sorting of columns and indexes in serialized schema caches.

    SchemaCache#encode_with no longer sorts a table's columns and indexes by name
    when writing the cache, restoring the pre-8.1 behavior.

    Jean Boussier

  • Fix only_columns to enumerate columns in the SELECT clause.

    Models using only_columns were generating SELECT * instead of an explicit
    column list, which could select columns that were meant to be excluded.

    sarub0b0

  • Fix eager_load with a composite primary key and an explicit select.

    The join dependency used the single primary key value to build aliases; for
    composite primary keys it now uses the full array of primary key columns, so
    eager loading with a custom select no longer drops the association records.

    fatkodima

  • Fix find_signed with a composite primary key.

    find_signed now wraps the decoded id in an array so find_by matches against
    all primary key columns, instead of silently returning nil.

    Kenta Ishizaki

  • Fix with_connection(prevent_permanent_checkout: true) clearing a sticky lease
    that was already set by lease_connection.

    A with_connection call with prevent_permanent_checkout: true no longer resets
    lease.sticky to its previous value when the connection was already sticky, so
    the connection remains checked out after the block.

    Ben Sheldon

  • Fix reset_counters to cast string ids to the primary key type.

    reset_counters called with a string id (the form ids take from request params)
    failed to find the record for both single and composite primary keys. Each id is
    now cast against its own column type.

    fatkodima

  • Fix belongs_to presence validation for composite foreign keys.

    The required-association validation only checked the first foreign key column.
    For composite foreign keys it now considers the association present only when
    none of the foreign key columns are nil, and changed when any of them changed.

    Felix Descoteaux

  • Fix preloading a belongs_to with a composite foreign key when some key columns
    are nil.

    The preloader now skips owners whose composite key has any nil component
    instead of issuing a query that matches unrelated rows.

    Rose Wiegley

  • Fix belongs_to inverse matching with composite foreign keys.

    inversable? compared a single foreign key column against a single primary key,
    so belongs_to associations with composite foreign keys never matched their
    inverse. Foreign key and primary key values are now compared component by
    component.

    Martin Samson

  • Fix validate_table_length! to ignore the schema prefix on PostgreSQL.

    Schema-qualified table names (e.g. "schema.very_long_table_name") were
    incorrectly rejected as exceeding the table name length limit because the schema
    prefix was counted. The schema is now stripped before checking the length.

    fatkodima

  • Fix passing Trilogy SSL options to mysql and mysqldump commands.

    Ngan Pham

  • Fix keepalive: false in database.yml falling back to the
    600 second default.

    Joe Sak

  • Fix connection checkout blocking past the configured checkout_timeout while
    waiting behind background connection maintenance.

    ConnectionPool#try_to_queue_for_background_connection waited up to a
    hardcoded 100 seconds for a connection tied up in maintenance (e.g. a keepalive
    ping), regardless of the pool's configured checkout_timeout. If maintenance
    stalled (a slow or unresponsive database server), checkout could block for far
    longer than the caller asked for.

    Joe Sak

  • Fix encrypted fixtures for JSON columns.

    Encrypted fixture values were serialized twice: once by the encrypted
    attribute type and again by the column type when the rows were inserted.
    For json/jsonb columns this stored the encrypted payload as a JSON
    string, which then failed to decrypt. The payload is now handed back in
    the column's cast form so it round-trips through the column type.

    Carlos Daniel Pohlod

  • Fix performance regression in method_missing for virtual SELECT alias
    attributes.

    Fixes #57183.

    Hammad Khan

  • Column defaults are no longer eagerly deserialized.

    Restore the Active Record 8.0 and older behavior.
    Column defaults are now whatever is returned by the database, generally a string.

    This was changed in 8.1.0 to make the attribute API more consistent,
    however it caused problems when the attribute type is later changed in the model.

    Typically, some databases treat boolean columns as small integers, ance once the
    default integer is casted to a boolean, it's not longer possible to change the
    attribute back into an integer in the model.

    Before:

    Person.columns_hash["age"].default # => 0

    After:

    Person.columns_hash["age"].default # => "0"

    See #58292.

    Jean Boussier

  • Preserve the declared parent order when dumping PostgreSQL INHERITS table options.

    The schema dumper read a table's inherited parents without an ORDER BY, so the
    INHERITS (...) clause in schema.rb could be emitted in a nondeterministic order.
    Parents are now ordered by pg_inherits.inhseqno.

    viralpraxis

  • Preserve SQLite partial and expression indexes when their stored SQL contains newlines.

    Javi Ramírez

  • Only use multi statement for SET TRANSACTION ISOLATION LEVEL; BEGIN if
    MySQL connection is configured to use multi statement.

    Eliseu Daroit, Hartley McGuire, Matthew Draper

  • Mark a connection unverified when a non-StandardError interrupts a query.

    A query interrupted by a non-StandardError, such as a fiber scheduler's
    cancel or a Timeout, leaves the connection desynced. Active Record
    previously returned it to the pool still marked verified, so the next
    checkout reused it and failed on a dead socket. The connection is now
    marked unverified, so it re-verifies and reconnects before its next use.

    Eliseu Daroit

  • Fix has_many and has_one associations on a new record returning an empty
    result when the owner has a composite primary key, even when every primary
    key column is populated.

    Jean-Samuel Aubry-Guzzi

  • Fix inverse association matching for has_many and has_one associations
    with association-specific composite primary keys.

    Hugo Vacher

  • Fix ActiveRecord::Base.with to call Object#with when given a block.

    The class-level with delegates to the relation's CTE query method, which
    does not accept a block. When a block is passed, it now delegates to
    Object#with instead, so it can be used to temporarily set attributes on
    the class for the duration of the block.

    Janko Marohnić

  • Fix serialize with coder: ActiveRecord::Coders::JSON silently double-encoding
    a native json/jsonb column.

    Kenta Ishizaki

  • Fix update_all / delete_all ignoring group and having, updating or
    deleting every row in the table instead of only the rows that satisfy the
    HAVING clause.

    Kenta Ishizaki

  • Fix ActiveRecord::Relation#cache_key / cache_version for a loaded collection
    containing a record without a timestamp.

    Kenta Ishizaki

  • Fix model filter_attributes to not add useless filters into config.filter_parameters.

    Proc and Regexp filters would be improperly turned into string matchers.
    Now they are skipped.

    Jonathan Calvert

  • Fix ActiveRecord::MessagePack serialization raising NoMethodError
    for any record with a populated time column, which made such records
    uncacheable through the MessagePack cache serializer.

    Kenta Ishizaki

  • Fix replacing or clearing a polymorphic has_one leaving a stale type column
    on the removed record.

    Kenta Ishizaki

  • Fix accepts_nested_attributes_for :limit miscounting a single-record hash.

    Kenta Ishizaki

  • Fix rename_index to preserve a partial index's WHERE for SQLite and older MySQL/MariaDB versions.

    Kenta Ishizaki

  • Fix PostgreSQL foreign_keys returning a corrupted to_table for a foreign key
    that references a table in a quoted schema.

    Kenta Ishizaki

  • Fix grouped calculations (e.g. count) grouped by a belongs_to association
    that points to a composite primary key model.

    Book.group(:order).count, where Book belongs_to :order and Order has a
    composite primary key, raised ArgumentError: Expected corresponding value for ["shop_id", "id"] to be an Array. The grouped result is now keyed by the
    associated records as it already is for single-column keys.

    Kenta Ishizaki

  • Fix has_many/has_one :through associations with disable_joins: true
    silently returning an empty result when the source points to a composite
    primary key model.

    Kenta Ishizaki

  • Fix collection association ids= writers (e.g. author.book_ids=) raising
    ActiveRecord::RecordNotFound for existing records when a composite primary
    key model is assigned string ids (the shape ids take from request params).

    Each id component is now cast against its own column type, instead of casting
    the whole tuple against an array of column names, which type_for_attribute
    can't resolve to a real type (so the cast was a no-op and the string ids
    never matched the loaded records).

    Kenta Ishizaki

  • Fix find with multiple composite primary key ids passed as strings
    silently returning [].

    Model.find([["1", "10"], ["1", "20"]]) (the shape ids take when they come
    from request parameters) returned an empty array instead of the records and
    without raising RecordNotFound. The ids were cast against the array of key
    column names as a whole — which is a no-op — so the string tuples never
    compared equal to the records' integer ids when ordering the result. Each
    component is now cast against its own column type, matching the documented
    coercion already performed for single-column keys.

    Kenta Ishizaki

  • Fix PostgreSQL daterange / tsrange / tstzrange schema dump producing
    invalid Ruby.

    The schema dumper used to render range defaults via Range#inspect, which
    falls back to Date#inspect / Time#inspect for the bounds. The resulting
    schema.rb literal (for example default: Mon, 01 Jan 2024..Wed, 01 Jan 2025)
    raised a SyntaxError on db:schema:load. The bounds are now rendered via
    the subtype's type_cast_for_schema, so date and timestamp range defaults
    round-trip through schema.rb like any other column.

    Kenta Ishizaki

  • Fix deadlock when pool-less connection materializes while fetching database
    server version.

    Hartley McGuire

  • Fix PostgreSQL range columns corrupting bounds that contain a comma.

    PostgreSQL::OID::Range#extract_bounds split a range's textual
    representation on the first comma, but PostgreSQL double-quotes any bound
    that itself contains a comma (e.g. a range over a text subtype). A value
    such as ["a,b","c,d") was therefore split inside the first quoted bound
    and read back with both endpoints corrupted. The split now skips over
    double-quoted segments when locating the separating comma.

    Kenta Ishizaki

  • Fix store accessor *_change and saved_change_to_* reporting a change
    for unchanged keys.

    When one key of a store column changed, the generated <key>_change and
    saved_change_to_<key> methods returned a [value, value] pair for the
    column's other keys too, even though their matching <key>_changed? /
    saved_change_to_<key>? correctly returned false and standard attribute
    _change / saved_change_to_* methods return nil when unchanged. The
    methods now return nil unless that specific key actually changed,
    matching their predicate counterparts.

    Kenta Ishizaki

  • Reduce number of queries when introspecting MySQL/MariaDB tables.

    A fix to support MariaDB function defaults caused the MySQL adapters to
    issue one query per column when introspecting tables.

    Now it only issue a single extra query per table, and only when using MariaDB.

    Iliana Hadzhiatanasova

  • Fully qualify query criterias in has_and_belongs_to_many associations.

    Ensure that scopes with the same column name but in different tables aren't lost
    when following an HABTM association.

    Philip Maina

  • Fix Active Record Pool Reaper thread leak after Parallelization#shutdown.

    After parallelized test runs, the parent process leaked the Active Record Pool
    Reaper thread, holding open connection pools and file descriptors for up to
    reaping_frequency seconds (or indefinitely if never reaped).

    Three fixes: Parallelization#shutdown now calls run_cleanup_hooks;
    Active Record registers a cleanup hook that discards all connection pools; and
    ConnectionPool#discard! now calls Reaper.discard_pool, which immediately
    kills and joins the reaper thread when no pools remain at that frequency.

    Ruy Rocha

  • Fix duplicate WHERE conditions in create_or_find_by.

    When create_or_find_by catches a RecordNotUnique error and retries the query, it now uses rewhere and take! to prevent duplicating existing scope conditions.

    Yavor Dashev

  • Fix ActiveRecord::QueryMethods#in_order_of when passing an out-of-range Integer

    To match the behavior of the Enumerable version, in_order_of now ignores an out-of-range Integer.

    tejanium

  • Revert alphabetical sorting of table columns inside schema.rb.

    Alphabetical sorting of table columns inside the schema creates improper production tables when using db:prepare.

    Bert McCutchen

  • Fix strict_loading violations ignored when using pluck

    Johnson Chan

  • Fix incorrect callback execution order when config.active_record.run_after_transaction_callbacks_in_order_defined = true
    and using after_commit and after_rollback callbacks with prepend: true.

    Joshua Young

  • Fix becomes to preserve marked_for_destruction?.

    Vincent Robert

  • MySQL error 1046 (ER_NO_DB_ERROR: No database selected) is now retryable as a ConnectionFailed exception

    Clay Harmon

Action View

  • Fix non-ASCII strict locals defaults rendering as mojibake.

    When a template declared a non-ASCII default in its locals: magic comment
    and its body was ASCII-only, the handler returned ASCII-8BIT code and the
    compiled method definition was retagged with it, corrupting the default.

    Carlos Daniel Pohlod

  • Fix the :ruby render tracker not being registered for ERB templates when
    eager_load is enabled.

    Gabriel Quaresma

  • Fix Encoding::CompatibilityError when digesting templates with non-ASCII
    content via DependencyTracker::RubyTracker.

    File-backed templates are loaded as ASCII-8BIT. RubyTracker now passes
    template.encode! to the handler (matching Template#compiled_source) so
    handlers such as Haml/Temple can concatenate static UTF-8 strings without
    raising. Fixes #58203.

    Edil Talantbek uulu

  • Fix week_field to not emit invalid week strings at ISO year boundaries.

    Kenta Ishizaki

  • Fix ActionView::TestCase#render to reset rendered.
    The behavior was changed when memoization was added in #51093. Now it once again conforms to the documentation.

    Jeroen Versteeg

  • Fix FormBuilder#to_partial_path returning nil for subclasses whose
    name does not end in Builder.

    Kenta Ishizaki

  • Fix collection_radio_buttons and collection_check_boxes generating
    a label for attribute that does not match the input id when a
    collection value is nil.

    Kenta Ishizaki

Action Pack

  • Fix the debug error page to not attempt to read source fragments from
    directory paths.

    Marco Roth

  • Apply source value mappings to dynamic Permissions Policy sources.

    Dynamic Permissions Policy sources (procs) now have source mappings applied
    to their resolved values, the same as static sources.

    Kenta Ishizaki

  • Allow ActionDispatch::Http::URL.path_for with trailing_slash: true and a
    blank path to accept query params and an anchor.

    Previously the blank path used a frozen "/", which raised a FrozenError
    when appending the query string.

    Kenta Ishizaki

  • Avoid mutating the params hash passed to ActionDispatch::Http::URL.url_for.

    Kenta Ishizaki

  • Honor falsy values (e.g. format: false, anchor: false) passed in the
    deprecated positional-hash form of routing DSL methods.

    Previously, false values were silently dropped without emitting a
    deprecation warning, causing the deprecated hash form to produce different
    routes than the keyword form.

    Kenta Ishizaki

  • Honor the deprecated namespace hash :path, :shallow_path, and
    :shallow_prefix options when passed as false.

    Kenta Ishizaki

  • Fix the deprecated scope hash :except option to apply to except
    instead of only.

    Kenta Ishizaki

  • Reject malformed hosts with extra ports in ActionDispatch::HostAuthorization.

    When an allowed host is configured with an explicit port, a Host header
    with an additional port (e.g. www.example.com:80:80) is no longer accepted.

    Andrii Furmanets

  • Fix url_for to leave out an optional part of a route when its value is a
    blank string, the same way it already does for nil.

    Before, the blank string ended up in the path, producing a URL the route
    itself cannot match:

    get "(/locale/:locale)/products(/:id)", to: "products#show"
    
    url_for(controller: "products", action: "show", locale: "", id: 123)
    # Before: "/locale//products/123"
    # After:  "/products/123"

    Blank strings for required parameters behave as before.

    Carl Dawson

  • Fix path normalization to handle mixed-case percent-encoding.

    Andrii Furmanets

  • Avoid loading ActionController::Live early in initializer, and introduce
    action_controller_live load hook.

    Adrianna Chang

  • Set the browser binary when preloading the Selenium driver for system tests.

    Selenium 4.45 stopped setting it as a side effect of getting the driver path,
    causing tests to fail with "cannot find Chrome binary".

    Titus Fortner

  • Fix Session::CacheStore to not generate a new session after dropping the current one.

    Kenta Ishizaki

  • Parse all three HTTP-date formats in the If-Modified-Since request header.

    If-Modified-Since carries an HTTP-date, which RFC 9110 allows in any of
    three formats (IMF-fixdate, RFC 850, or asctime), and requires recipients to
    accept all three. The header was parsed with Time.rfc2822, which only
    accepts the IMF-fixdate format, and the parse failure was swallowed — so a
    conditional GET using an RFC 850 or asctime date silently failed to produce
    a 304 Not Modified and re-sent the full response. It is now parsed with
    Time.httpdate, consistent with how Last-Modified and Date are read.

    Kenta Ishizaki

  • Fix response steam buffers compatibility with IO.copy_stream.

    IO.copy_stream(src, response.stream) raised TypeError: no implicit conversion of Array into Integer because Buffer#write returned the
    buffer array instead of an Integer (bytes written). Additionally, the
    written data could be silently corrupted because IO.copy_stream
    reuses its internal string buffer after write returns — storing a
    reference without dup meant the buffered content was later mutated.

    Both ActionDispatch::Response::Buffer#write and
    ActionController::Live::Buffer#write are affected.

    Gabriel Quaresma

Active Job

  • Fix retry_job to preserve wait_until, queue, and priority options when
    enqueue_after_transaction_commit defers the enqueue.

    Said Kaldybaev

  • Clear a stale enqueue_error when perform_all_later successfully re-enqueues a job.

    Kenta Ishizaki

  • Clear enqueue_error when a job is successfully re-enqueued via enqueue.

    Kenta Ishizaki

  • Fix resume_job not receiving the exception when resuming a continuation after
    an error, causing exception_executions to not be recorded correctly.

    Kenta Ishizaki

  • Fix ActiveJob.perform_all_later not being available until ActiveJob::Enqueuing
    was autoloaded.

    fatkodima

Action Mailer

  • Fix ActionMailer.deliver_all_later not being available until
    ActionMailer::MessageDelivery was autoloaded.

    fatkodima

  • Fix ActionMailer::Base.mail not returning a MessageDelivery in Rails 8.1+.

    Andrii Furmanets

Action Cable

  • Allow redis-rb 6 in the Action Cable Redis subscription adapter.

    Shuta Mugikura

  • Fix the PostgreSQL subscription adapter dropping broadcasts to long multibyte stream names.

    PostgreSQL identifiers are limited to 63 bytes, and the adapter hashes any
    name over that limit to avoid silent truncation. The length check was done on
    character count rather than byte size, so a multibyte stream name with 63 or
    fewer characters but more than 63 bytes was silently truncated by PostgreSQL.

    Kenta Ishizaki

Active Storage

  • Warn instead of aborting boot when image_processing 2.x is installed without ruby-vips
    or mini_magick.

    Both gems became soft dependencies in image_processing 2.0, and the LoadError raised for
    a missing one names that gem instead of image_processing. Active Storage did not recognize
    the message, so it re-raised rather than logging its usual warning.

    Fixes #58413.

    Janko Marohnić

  • Fix MirrorService#mirror losing blob metadata when copying to mirrors.

    Mirrored copies on S3, Azure, and GCS were served as application/octet-stream
    because content_type, filename, disposition, and custom_metadata were
    dropped. Forward the blob's service_metadata to each mirror's upload.

    Fixes #57270.

    Maksim Romanov + Andrii Furmanets

  • Prevent ActiveStorage.touch_attachment_records = false from crashing the attachment of a Blob.

    When ActiveStorage.touch_attachment_records was set to false, attaching a existing Blob to a Record
    would raise an error. This is now fixed.

    Edouard Chin

  • Fix MirrorService#mirror raising ActiveStorage::IntegrityError when
    mirroring without a checksum (e.g., track_variants: false).

    Denis Savchuk

  • Preserve attachment changes when converting record to another class using STI.

    fatkodima

  • Correct unexpected behavior resulting from dependent: :purge when using
    has_one_attached or has_many_attached. Fixes #36423.

    Mark Oveson

  • Define as_json on ActiveStorage::Attached::One and ActiveStorage::Attached::Many.

    The proxies hold a back-reference to the owning record in @record. Without an explicit
    as_json, the default Object#as_json fall back serialized instance_values, which made
    record.to_json recurse infinitely whenever the attached name collided with a model
    attribute (e.g. an ignored_columns column brought back by select('*')).

    Attached::One#as_json now returns the attachment record's JSON when attached and nil
    otherwise. Attached::Many#as_json returns the attachment records' JSON as an array.

    Renxiang Cai

  • Fix Rails hanging when generating video previews

    When Rails runs in a background process group, ffmpeg's attempt to configure the terminal for
    interactive input would send SIGTTOU to the Rails process, suspending it indefinitely.

    Fixed by explicitly passing /dev/null to ffmpeg's stdin.

    Jonathan del Strother

Action Mailbox

  • No changes.

Action Text

  • No changes.

Railties

  • Include the offending value in the secret_key_base= error message.

    Jean Boussier

  • Load database config when a connection is absent from the shared section.

    database_configuration no longer raises NoMethodError when a shared
    config section is missing a subsection for a particular connection name.

    Kenta Ishizaki

  • Round-trip the null: false attribute modifier in GeneratedAttribute#to_s.

    rails generate now emits the ! modifier for attributes with null: false,
    so the generated command string can be used to regenerate the same migration.

    Kenta Ishizaki

  • Fix infinite route reload when after_routes_loaded hooks access routes.

    The :loading state is now held across after_routes_loaded hooks, so a
    hook that touches routes no longer triggers a redundant reload.

    Chedli Bourguiba

  • Fix LazyRouteSet thrashing when url_helpers are included into Object.

    method_missing and respond_to_missing? now only trigger a route reload
    for methods ending in _path or _url, preventing every respond_to?
    call from re-entering the route loader.

    Chedli Bourguiba

  • Add RoutesReloader#loaded to check whether routes have been loaded.

    Rafael Mendonça França

  • Mark routes as loaded when the routes reloader executes standalone.

    RoutesReloader#execute now sets the load state to loaded, so calling
    it directly (outside of execute_unless_loaded) no longer leaves the
    reloader in a state where routes are considered unloaded.

    Kenta Ishizaki

  • Make mounted route helpers (e.g. main_app, engine mount proxies) trigger
    the lazy route load instead of raising NoMethodError when called before
    routes are drawn.

    Named url helpers already loaded routes on demand, but mounted helpers are
    only defined when mount runs during the route draw, so calling one first
    (in the console or a test) failed until something else drew the routes.

    Abdelkader Boudih

  • Make lazy route loading thread-safe.

    Since routes are drawn on the first request in environments where
    config.eager_load is false (development and test by default),
    concurrent first requests could dispatch against an empty or half-drawn
    route set, resulting in a 404 for a perfectly valid route. Route drawing
    is now synchronized: concurrent requests wait for the initial draw to
    complete and are then dispatched against the fully drawn route set.

    grk

  • Validate subcommand in rails plugin command.

    rails plugin foo bar silently ignored the invalid subcommand "foo"
    and proceeded to create a plugin named "bar". Now it prints an error
    and exits with status 1.

    Fixes #57430.

    Ruy Rocha

  • Prevent the internal development welcome route from being duplicated on route reloads.

    Elliot Temple

Guides

  • No changes.

Don't miss a new activerecord release

NewReleases is sending notifications on new releases.