UNCLASSIFIED - NO CUI

Skip to content

Update dependency activesupport to v7

This MR contains the following updates:

Package Type Update Change
activesupport (source, changelog) ironbank-rubygems major 5.2.8.1 -> 7.1.2

Release Notes

rails/rails (activesupport)

v7.1.2: 7.1.2

Compare Source

Active Support

  • Fix :expires_in option for RedisCacheStore#write_multi.

    fatkodima

  • Fix deserialization of non-string "purpose" field in Message serializer

    Jacopo Beschi

  • Prevent global cache options being overwritten when setting dynamic options inside a ActiveSupport::Cache::Store#fetch block.

    Yasha Krasnou

  • Fix missing require resulting in NoMethodError when running bin/rails secrets:show or bin/rails secrets:edit.

    Stephen Ierodiaconou

  • Ensure {down,up}case_first returns non-frozen string.

    Jonathan Hefner

  • Fix #to_fs(:human_size) to correctly work with negative numbers.

    Earlopain

  • Fix BroadcastLogger#dup so that it duplicates the logger's broadcasts.

    Andrew Novoselac

  • Fix issue where bootstrap.rb overwrites the level of a BroadcastLogger's broadcasts.

    Andrew Novoselac

  • Fix ActiveSupport::Cache to handle outdated Marshal payload from Rails 6.1 format.

    Active Support's Cache is supposed to treat a Marshal payload that can no longer be deserialized as a cache miss. It fail to do so for compressed payload in the Rails 6.1 legacy format.

    Jean Boussier

  • Fix OrderedOptions#dig for array indexes.

    fatkodima

  • Fix time travel helpers to work when nested using with separate classes.

    fatkodima

  • Fix delete_matched for file cache store to work with keys longer than the max filename size.

    fatkodima and Jonathan Hefner

  • Fix compatibility with the semantic_logger gem.

    The semantic_logger gem doesn't behave exactly like stdlib logger in that SemanticLogger#level returns a Symbol while stdlib Logger#level returns an Integer.

    This caused the various LogSubscriber classes in Rails to break when assigned a SemanticLogger instance.

    Jean Boussier, ojab

Active Model

  • Make ==(other) method of AttributeSet safe.

    Dmitry Pogrebnoy

Active Record

  • Fix renaming primary key index when renaming a table with a UUID primary key in PostgreSQL.

    fatkodima

  • Fix where(field: values) queries when field is a serialized attribute (for example, when field uses ActiveRecord::Base.serialize or is a JSON column).

    João Alves

  • Prevent marking broken connections as verified.

    Daniel Colson

  • 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_name now returns nil instead of raising "undefined method abstract_class? for Object:Class".

    a5-stable

  • Fix upserting for custom :on_duplicate and :unique_by consisting of all inserts keys.

    fatkodima

  • Fixed an issue where saving a record could innappropriately dup its attributes.

    Jonathan Hefner

  • Dump schema only for a specific db for rollback/up/down tasks for multiple dbs.

    fatkodima

  • Fix NoMethodError when casting a PostgreSQL money value 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

  • Re-enable support for using enum with non-column-backed attributes. Non-column-backed attributes must be previously declared with an explicit type. For example:

    class Post < ActiveRecord::Base
      attribute :topic, :string
      enum topic: %i[science tech engineering math]
    end

    Jonathan Hefner

  • Raise on foreign_key: being passed as an array in associations

    Nikita Vasilevsky

  • Return back maximum allowed PostgreSQL table name to 63 characters.

    fatkodima

  • Fix detecting IDENTITY columns for PostgreSQL < 10.

    fatkodima

Action View

  • Fix the number_to_human_size view helper to correctly work with negative numbers.

    Earlopain

  • Automatically discard the implicit locals injected by collection rendering for template that can't accept them

    When rendering a collection, two implicit variables are injected, which breaks templates with strict locals.

    Now they are only passed if the template will actually accept them.

    Yasha Krasnou, Jean Boussier

  • Fix @rails/ujs calling start() an extra time when using bundlers

    Hartley McGuire, Ryunosuke Sato

  • Fix the capture view helper compatibility with HAML and Slim

    When a blank string was captured in HAML or Slim (and possibly other template engines) it would instead return the entire buffer.

    Jean Boussier

Action Pack

  • Fix a race condition that could cause a Text file busy - chromedriver error with parallel system tests

    Matt Brictson

  • Fix StrongParameters#extract_value to include blank values

    Otherwise composite parameters may not be parsed correctly when one of the component is blank.

    fatkodima, Yasha Krasnou, Matthias Eiglsperger

  • Add racc as a dependency since it will become a bundled gem in Ruby 3.4.0

    Hartley McGuire

  • Support handling Enumerator for non-buffered responses.

    Zachary Scott

Active Job

  • No changes.

Action Mailer

  • No changes.

Action Cable

  • No changes.

Active Storage

  • No changes.

Action Mailbox

  • No changes.

Action Text

  • Compile ESM package that can be used directly in the browser as actiontext.esm.js

    Matias Grunberg

  • Fix using actiontext.js with Sprockets

    Matias Grunberg

  • Upgrade Trix to 2.0.7

    Hartley McGuire

  • Fix using Trix with Sprockets

    Hartley McGuire

Railties

  • Fix running db:system:change when app has no Dockerfile.

    Hartley McGuire

  • If you accessed config.eager_load_paths and friends, later changes to config.paths were not reflected in the expected auto/eager load paths. Now, they are.

    This bug has been latent since Rails 3.

    Fixes #​49629.

    Xavier Noria

v7.1.1: 7.1.1

Compare Source

Active Support

  • Add support for keyword arguments when delegating calls to custom loggers from ActiveSupport::BroadcastLogger.

    Jenny Shen

  • NumberHelper: handle objects responding to_d.

    fatkodima

  • Fix RedisCacheStore to properly set the TTL when incrementing or decrementing.

    This bug was only impacting Redis server older than 7.0.

    Thomas Countz

  • Fix MemoryStore to prevent race conditions when incrementing or decrementing.

    Pierre Jambet

Active Model

  • No changes.

Active Record

  • Fix auto populating IDENTITY columns for PostgreSQL.

    fatkodima

  • Fix "ArgumentError: wrong number of arguments (given 3, expected 2)" when down migrating rename_table in older migrations.

    fatkodima

  • Do not require the Action Text, Active Storage and Action Mailbox tables to be present when running when running test on CI.

    Rafael Mendonça França

Action View

  • Updated @rails/ujs files to ignore certain data-* attributes when element is contenteditable.

    This fix was already landed in >= 7.0.4.3, < 7.1.0. [CVE-2023-23913]

    Ryunosuke Sato

Action Pack

  • No changes.

Active Job

  • Don't log enqueuing details when the job wasn't enqueued.

    Dustin Brown

Action Mailer

  • No changes.

Action Cable

  • No changes.

Active Storage

  • No changes.

Action Mailbox

  • No changes.

Action Text

  • No changes.

Railties

  • Ensures the Rails generated Dockerfile uses correct ruby version and matches Gemfile.

    Abhay Nikam

v7.1.0: 7.1.0

Compare Source

Active Support

  • Fix AS::MessagePack with ENV["RAILS_MAX_THREADS"].

    Jonathan Hefner

  • Add a new public API for broadcasting logs

    This feature existed for a while but was until now a private API. Broadcasting log allows to send log message to difference sinks (STDOUT, a file ...) and is used by default in the development environment to write logs both on STDOUT and in the "development.log" file.

    Basic usage:

    stdout_logger = Logger.new(STDOUT)
    file_logger = Logger.new("development.log")
    broadcast = ActiveSupport::BroadcastLogger.new(stdout_logger, file_logger)
    
    broadcast.info("Hello!") # The "Hello!" message is written on STDOUT and in the log file.

    Adding other sink(s) to the broadcast:

    broadcast = ActiveSupport::BroadcastLogger.new
    broadcast.broadcast_to(Logger.new(STDERR))

    Remove a sink from the broadcast:

    stdout_logger = Logger.new(STDOUT)
    broadcast = ActiveSupport::BroadcastLogger.new(stdout_logger)
    
    broadcast.stop_broadcasting_to(stdout_logger)

    Edouard Chin

  • Fix Range#overlap? not taking empty ranges into account on Ruby < 3.3

    Nobuyoshi Nakada, Shouichi Kamiya, Hartley McGuire

  • Use Ruby 3.3 Range#overlap? if available

    Yasuo Honda

  • Add bigdecimal as Active Support dependency that is a bundled gem candidate for Ruby 3.4.

    bigdecimal 3.1.4 or higher version will be installed. Ruby 2.7 and 3.0 users who want bigdecimal version 2.0.0 or 3.0.0 behavior as a default gem, pin the bigdecimal version in your application Gemfile.

    Koichi ITO

  • Add drb, mutex_m and base64 that are bundled gem candidates for Ruby 3.4

    Yasuo Honda

  • When using cache format version >= 7.1 or a custom serializer, expired and version-mismatched cache entries can now be detected without deserializing their values.

    Jonathan Hefner

  • Make all cache stores return a boolean for #delete

    Previously the RedisCacheStore#delete would return 1 if the entry exists and 0 otherwise. Now it returns true if the entry exists and false otherwise, just like the other stores.

    The FileStore would return nil if the entry doesn't exists and returns false now as well.

    Petrik de Heus

  • Active Support cache stores now support replacing the default compressor via a :compressor option. The specified compressor must respond to deflate and inflate. For example:

    module MyCompressor
      def self.deflate(string)

compression logic...

    end

    def self.inflate(compressed)

decompression logic...

    end
  end

  config.cache_store = :redis_cache_store, { compressor: MyCompressor }
  ```

*Jonathan Hefner*
  • Active Support cache stores now support a :serializer option. Similar to the :coder option, serializers must respond to dump and load. However, serializers are only responsible for serializing a cached value, whereas coders are responsible for serializing the entire ActiveSupport::Cache::Entry instance. Additionally, the output from serializers can be automatically compressed, whereas coders are responsible for their own compression.

    Specifying a serializer instead of a coder also enables performance optimizations, including the bare string optimization introduced by cache format version 7.1.

    The :serializer and :coder options are mutually exclusive. Specifying both will raise an ArgumentError.

    Jonathan Hefner

  • Fix ActiveSupport::Inflector.humanize(nil) raising NoMethodError: undefined method `end_with?' for nil:NilClass.

    James Robinson

  • Don't show secrets for ActiveSupport::KeyGenerator#inspect.

    Before:

    ActiveSupport::KeyGenerator.new(secret).inspect
    "#<ActiveSupport::KeyGenerator:0x0000000104888038 ... @&#8203;secret=\"\\xAF\\bFh]LV}q\\nl\\xB2U\\xB3 ... >"

    After:

    ActiveSupport::KeyGenerator::Aes256Gcm(secret).inspect
    "#<ActiveSupport::KeyGenerator:0x0000000104888038>"

    Petrik de Heus

  • Improve error message when EventedFileUpdateChecker is used without a compatible version of the Listen gem

    Hartley McGuire

  • Add :report behavior for Deprecation

    Setting config.active_support.deprecation = :report uses the error reporter to report deprecation warnings to ActiveSupport::ErrorReporter.

    Deprecations are reported as handled errors, with a severity of :warning.

    Useful to report deprecations happening in production to your bug tracker.

    Étienne Barrié

  • Rename Range#overlaps? to #overlap? and add alias for backwards compatibility

    Christian Schmidt

  • Fix EncryptedConfiguration returning incorrect values for some Hash methods

    Hartley McGuire

  • Don't show secrets for MessageEncryptor#inspect.

    Before:

    ActiveSupport::MessageEncryptor.new(secret, cipher: "aes-256-gcm").inspect
    "#<ActiveSupport::MessageEncryptor:0x0000000104888038 ... @&#8203;secret=\"\\xAF\\bFh]LV}q\\nl\\xB2U\\xB3 ... >"

    After:

    ActiveSupport::MessageEncryptor.new(secret, cipher: "aes-256-gcm").inspect
    "#<ActiveSupport::MessageEncryptor:0x0000000104888038>"

    Petrik de Heus

  • Don't show contents for EncryptedConfiguration#inspect.

    Before:

    Rails.application.credentials.inspect
    "#<ActiveSupport::EncryptedConfiguration:0x000000010d2b38e8 ... @&#8203;config={:secret=>\"something secret\"} ... @&#8203;key_file_contents=\"915e4ea054e011022398dc242\" ...>"

    After:

    Rails.application.credentials.inspect
    "#<ActiveSupport::EncryptedConfiguration:0x000000010d2b38e8>"

    Petrik de Heus

  • ERB::Util.html_escape_once always returns an html_safe string.

    This method previously maintained the html_safe? property of a string on the return value. Because this string has been escaped, however, not marking it as html_safe causes entities to be double-escaped.

    As an example, take this view snippet:

    <p><%= html_escape_once("this & that &amp; the other") %></p>

    Before this change, that would be double-escaped and render as:

    <p>this &amp;amp; that &amp;amp; the other</p>

    After this change, it renders correctly as:

    <p>this &amp; that &amp; the other</p>

    Fixes #​48256

    Mike Dalessio

  • Deprecate SafeBuffer#clone_empty.

    This method has not been used internally since Rails 4.2.0.

    Mike Dalessio

  • MessageEncryptor, MessageVerifier, and config.active_support.message_serializer now accept :message_pack and :message_pack_allow_marshal as serializers. These serializers require the msgpack gem (>= 1.7.0).

    The Message Pack format can provide improved performance and smaller payload sizes. It also supports round-tripping some Ruby types that are not supported by JSON. For example:

    verifier = ActiveSupport::MessageVerifier.new("secret")
    data = [{ a: 1 }, { b: 2 }.with_indifferent_access, 1.to_d, Time.at(0, 123)]
    message = verifier.generate(data)

BEFORE with config.active_support.message_serializer = :json

  verifier.verified(message)

=> [{"a"=>1}, {"b"=>2}, "1.0", "1969-12-31T18:00:00.000-06:00"]

  verifier.verified(message).map(&:class)

=> [Hash, Hash, String, String]

AFTER with config.active_support.message_serializer = :message_pack

  verifier.verified(message)

=> [{:a=>1}, {"b"=>2}, 0.1e1, 1969-12-31 18:00:00.000123 -0600]

  verifier.verified(message).map(&:class)

=> [Hash, ActiveSupport::HashWithIndifferentAccess, BigDecimal, Time]

  ```

The `:message_pack` serializer can fall back to deserializing with
`ActiveSupport::JSON` when necessary, and the `:message_pack_allow_marshal`
serializer can fall back to deserializing with `Marshal` as well as
`ActiveSupport::JSON`. Additionally, the `:marshal`, `:json`, and
`:json_allow_marshal` serializers can now fall back to deserializing with
`ActiveSupport::MessagePack` when necessary. These behaviors ensure old
messages can still be read so that migration is easier.

*Jonathan Hefner*
  • A new 7.1 cache format is available which includes an optimization for bare string values such as view fragments.

    The 7.1 cache format is used by default for new apps, and existing apps can enable the format by setting config.load_defaults 7.1 or by setting config.active_support.cache_format_version = 7.1 in config/application.rb or a config/environments/*.rb file.

    Cache entries written using the 6.1 or 7.0 cache formats can be read when using the 7.1 format. To perform a rolling deploy of a Rails 7.1 upgrade, wherein servers that have not yet been upgraded must be able to read caches from upgraded servers, leave the cache format unchanged on the first deploy, then enable the 7.1 cache format on a subsequent deploy.

    Jonathan Hefner

  • Active Support cache stores can now use a preconfigured serializer based on ActiveSupport::MessagePack via the :serializer option:

    config.cache_store = :redis_cache_store, { serializer: :message_pack }

    The :message_pack serializer can reduce cache entry sizes and improve performance, but requires the msgpack gem (>= 1.7.0).

    The :message_pack serializer can read cache entries written by the default serializer, and the default serializer can now read entries written by the :message_pack serializer. These behaviors make it easy to migrate between serializer without invalidating the entire cache.

    Jonathan Hefner

  • Object#deep_dup no longer duplicate named classes and modules.

    Before:

    hash = { class: Object, module: Kernel }
    hash.deep_dup # => {:class=>#<Class:0x00000001063ffc80>, :module=>#<Module:0x00000001063ffa00>}

    After:

    hash = { class: Object, module: Kernel }
    hash.deep_dup # => {:class=>Object, :module=>Kernel}

    Jean Boussier

  • Consistently raise an ArgumentError if the ActiveSupport::Cache key is blank.

    Joshua Young

  • Deprecate usage of the singleton ActiveSupport::Deprecation.

    All usage of ActiveSupport::Deprecation as a singleton is deprecated, the most common one being ActiveSupport::Deprecation.warn. Gem authors should now create their own deprecator (ActiveSupport::Deprecation object), and use it to emit deprecation warnings.

    Calling any of the following without specifying a deprecator argument is also deprecated:

    • Module.deprecate
    • deprecate_constant
    • DeprecatedObjectProxy
    • DeprecatedInstanceVariableProxy
    • DeprecatedConstantProxy
    • deprecation-related test assertions

    Use of ActiveSupport::Deprecation.silence and configuration methods like behavior=, disallowed_behavior=, disallowed_warnings= should now be aimed at the application's deprecators.

    Rails.application.deprecators.silence do

code that emits deprecation warnings

end
```

If your gem has a Railtie or Engine, it's encouraged to add your deprecator to the application's deprecators, that
way the deprecation related configuration options will apply to it as well, e.g.
`config.active_support.report_deprecations` set to `false` in the production environment will also disable your
deprecator.

```ruby
initializer "my_gem.deprecator" do |app|
  app.deprecators[:my_gem] = MyGem.deprecator
end
```

*Étienne Barrié*
  • Add Object#with to set and restore public attributes around a block

    client.timeout # => 5
    client.with(timeout: 1) do
      client.timeout # => 1
    end
    client.timeout # => 5

    Jean Boussier

  • Remove deprecated support to generate incorrect RFC 4122 UUIDs when providing a namespace ID that is not one of the constants defined on Digest::UUID.

    Rafael Mendonça França

  • Deprecate config.active_support.use_rfc4122_namespaced_uuids.

    Rafael Mendonça França

  • Remove implicit conversion of objects into String by ActiveSupport::SafeBuffer.

    Rafael Mendonça França

  • Remove deprecated active_support/core_ext/range/include_time_with_zone file.

    Rafael Mendonça França

  • Deprecate config.active_support.remove_deprecated_time_with_zone_name.

    Rafael Mendonça França

  • Remove deprecated override of ActiveSupport::TimeWithZone.name.

    Rafael Mendonça França

  • Deprecate config.active_support.disable_to_s_conversion.

    Rafael Mendonça França

  • Remove deprecated option to passing a format to #to_s in Array, Range, Date, DateTime, Time, BigDecimal, Float and, Integer.

    Rafael Mendonça França

  • Remove deprecated ActiveSupport::PerThreadRegistry.

    Rafael Mendonça França

  • Remove deprecated override of Enumerable#sum.

    Rafael Mendonça França

  • Deprecated initializing a ActiveSupport::Cache::MemCacheStore with an instance of Dalli::Client.

    Deprecate the undocumented option of providing an already-initialized instance of Dalli::Client to ActiveSupport::Cache::MemCacheStore. Such clients could be configured with unrecognized options, which could lead to unexpected behavior. Instead, provide addresses as documented.

    aledustet

  • Stub Time.new() in TimeHelpers#travel_to

    travel_to Time.new(2004, 11, 24) do

Inside the travel_to block Time.new is stubbed

    assert_equal 2004, Time.new.year
  end
  ```

*fatkodima*
  • Raise ActiveSupport::MessageEncryptor::InvalidMessage from ActiveSupport::MessageEncryptor#decrypt_and_verify regardless of cipher. Previously, when a MessageEncryptor was using a non-AEAD cipher such as AES-256-CBC, a corrupt or tampered message would raise ActiveSupport::MessageVerifier::InvalidSignature. Now, all ciphers raise the same error:

    encryptor = ActiveSupport::MessageEncryptor.new("x" * 32, cipher: "aes-256-gcm")
    message = encryptor.encrypt_and_sign("message")
    encryptor.decrypt_and_verify(message.next)

=> raises ActiveSupport::MessageEncryptor::InvalidMessage

  encryptor = ActiveSupport::MessageEncryptor.new("x" * 32, cipher: "aes-256-cbc")
  message = encryptor.encrypt_and_sign("message")
  encryptor.decrypt_and_verify(message.next)

BEFORE:

=> raises ActiveSupport::MessageVerifier::InvalidSignature

AFTER:

=> raises ActiveSupport::MessageEncryptor::InvalidMessage

  ```

*Jonathan Hefner*
  • Support nil original values when using ActiveSupport::MessageVerifier#verify. Previously, MessageVerifier#verify did not work with nil original values, though both MessageVerifier#verified and MessageEncryptor#decrypt_and_verify do:

    encryptor = ActiveSupport::MessageEncryptor.new(secret)
    message = encryptor.encrypt_and_sign(nil)
    
    encryptor.decrypt_and_verify(message)

=> nil

  verifier = ActiveSupport::MessageVerifier.new(secret)
  message = verifier.generate(nil)

  verifier.verified(message)

=> nil

  verifier.verify(message)

BEFORE:

=> raises ActiveSupport::MessageVerifier::InvalidSignature

AFTER:

=> nil

  ```

*Jonathan Hefner*
  • Maintain html_safe? on html_safe strings when sliced with slice, slice!, or chr method.

    Previously, html_safe? was only maintained when the html_safe strings were sliced with [] method. Now, slice, slice!, and chr methods will maintain html_safe? like [] method.

    string = "<div>test</div>".html_safe
    string.slice(0, 1).html_safe? # => true
    string.slice!(0, 1).html_safe? # => true

maintain html_safe? after the slice!

string.html_safe? # => true
string.chr.html_safe? # => true
```

*Michael Go*
  • Add Object#in? support for open ranges.

    assert Date.today.in?(..Date.tomorrow)
    assert_not Date.today.in?(Date.tomorrow..)

    Ignacio Galindo

  • config.i18n.raise_on_missing_translations = true now raises on any missing translation.

    Previously it would only raise when called in a view or controller. Now it will raise anytime I18n.t is provided an unrecognised key.

    If you do not want this behaviour, you can customise the i18n exception handler. See the upgrading guide or i18n guide for more information.

    Alex Ghiculescu

  • ActiveSupport::CurrentAttributes now raises if a restricted attribute name is used.

    Attributes such as set and reset cannot be used as they clash with the CurrentAttributes public API.

    Alex Ghiculescu

  • HashWithIndifferentAccess#transform_keys now takes a Hash argument, just as Ruby's Hash#transform_keys does.

    Akira Matsuda

  • delegate now defines method with proper arity when delegating to a Class. With this change, it defines faster method (3.5x faster with no argument). However, in order to gain this benefit, the delegation target method has to be defined before declaring the delegation.

This defines 3.5 times faster method than before

class C
  def self.x() end
  delegate :x, to: :class
end

class C

This works but silently falls back to old behavior because

delegate cannot find the definition of x

  delegate :x, to: :class
  def self.x() end
end
```

*Akira Matsuda*
  • assert_difference message now includes what changed.

    This makes it easier to debug non-obvious failures.

    Before:

    "User.count" didn't change by 32.
    Expected: 1611
      Actual: 1579

    After:

    "User.count" didn't change by 32, but by 0.
    Expected: 1611
      Actual: 1579

    Alex Ghiculescu

  • Add ability to match exception messages to assert_raises assertion

    Instead of this

    error = assert_raises(ArgumentError) do
      perform_service(param: 'exception')
    end
    assert_match(/incorrect param/i, error.message)

    you can now write this

    assert_raises(ArgumentError, match: /incorrect param/i) do
      perform_service(param: 'exception')
    end

    fatkodima

  • Add Rails.env.local? shorthand for Rails.env.development? || Rails.env.test?.

    DHH

  • ActiveSupport::Testing::TimeHelpers now accepts named with_usec argument to freeze_time, travel, and travel_to methods. Passing true prevents truncating the destination time with change(usec: 0).

    KevSlashNull, and serprex

  • ActiveSupport::CurrentAttributes.resets now accepts a method name

    The block API is still the recommended approach, but now both APIs are supported:

    class Current < ActiveSupport::CurrentAttributes
      resets { Time.zone = nil }
      resets :clear_time_zone
    end

    Alex Ghiculescu

  • Ensure ActiveSupport::Testing::Isolation::Forking closes pipes

    Previously, Forking.run_in_isolation opened two ends of a pipe. The fork process closed the read end, wrote to it, and then terminated (which presumably closed the file descriptors on its end). The parent process closed the write end, read from it, and returned, never closing the read end.

    This resulted in an accumulation of open file descriptors, which could cause errors if the limit is reached.

    Sam Bostock

  • Fix Time#change and Time#advance for times around the end of Daylight Saving Time.

    Previously, when Time#change or Time#advance constructed a time inside the final stretch of Daylight Saving Time (DST), the non-DST offset would always be chosen for local times:

DST ended just before 2021-11-07 2:00:00 AM in US/Eastern.

ENV["TZ"] = "US/Eastern"

time = Time.local(2021, 11, 07, 00, 59, 59) + 1

=> 2021-11-07 01:00:00 -0400

time.change(day: 07)

=> 2021-11-07 01:00:00 -0500

time.advance(seconds: 0)

=> 2021-11-07 01:00:00 -0500

time = Time.local(2021, 11, 06, 01, 00, 00)

=> 2021-11-06 01:00:00 -0400

time.change(day: 07)

=> 2021-11-07 01:00:00 -0500

time.advance(days: 1)

=> 2021-11-07 01:00:00 -0500

```

And the DST offset would always be chosen for times with a `TimeZone`
object:

```ruby
Time.zone = "US/Eastern"

time = Time.new(2021, 11, 07, 02, 00, 00, Time.zone) - 3600

=> 2021-11-07 01:00:00 -0500

time.change(day: 07)

=> 2021-11-07 01:00:00 -0400

time.advance(seconds: 0)

=> 2021-11-07 01:00:00 -0400

time = Time.new(2021, 11, 8, 01, 00, 00, Time.zone)

=> 2021-11-08 01:00:00 -0500

time.change(day: 07)

=> 2021-11-07 01:00:00 -0400

time.advance(days: -1)

=> 2021-11-07 01:00:00 -0400

```

Now, `Time#change` and `Time#advance` will choose the offset that matches
the original time's offset when possible:

```ruby
ENV["TZ"] = "US/Eastern"

time = Time.local(2021, 11, 07, 00, 59, 59) + 1

=> 2021-11-07 01:00:00 -0400

time.change(day: 07)

=> 2021-11-07 01:00:00 -0400

time.advance(seconds: 0)

=> 2021-11-07 01:00:00 -0400

time = Time.local(2021, 11, 06, 01, 00, 00)

=> 2021-11-06 01:00:00 -0400

time.change(day: 07)

=> 2021-11-07 01:00:00 -0400

time.advance(days: 1)

=> 2021-11-07 01:00:00 -0400

Time.zone = "US/Eastern"

time = Time.new(2021, 11, 07, 02, 00, 00, Time.zone) - 3600

=> 2021-11-07 01:00:00 -0500

time.change(day: 07)

=> 2021-11-07 01:00:00 -0500

time.advance(seconds: 0)

=> 2021-11-07 01:00:00 -0500

time = Time.new(2021, 11, 8, 01, 00, 00, Time.zone)

=> 2021-11-08 01:00:00 -0500

time.change(day: 07)

=> 2021-11-07 01:00:00 -0500

time.advance(days: -1)

=> 2021-11-07 01:00:00 -0500

```

*Kevin Hall*, *Takayoshi Nishida*, and *Jonathan Hefner*
  • Fix MemoryStore to preserve entries TTL when incrementing or decrementing

    This is to be more consistent with how MemCachedStore and RedisCacheStore behaves.

    Jean Boussier

  • Rails.error.handle and Rails.error.record filter now by multiple error classes.

    Rails.error.handle(IOError, ArgumentError) do
      1 + '1' # raises TypeError
    end
    1 + 1 # TypeErrors are not IOErrors or ArgumentError, so this will *not* be handled

    Martin Spickermann

  • Class#subclasses and Class#descendants now automatically filter reloaded classes.

    Previously they could return old implementations of reloadable classes that have been dereferenced but not yet garbage collected.

    They now automatically filter such classes like DescendantTracker#subclasses and DescendantTracker#descendants.

    Jean Boussier

  • Rails.error.report now marks errors as reported to avoid reporting them twice.

    In some cases, users might want to report errors explicitly with some extra context before letting it bubble up.

    This also allows to safely catch and report errors outside of the execution context.

    Jean Boussier

  • Add assert_error_reported and assert_no_error_reported

    Allows to easily asserts an error happened but was handled

    report = assert_error_reported(IOError) do

...

end
assert_equal "Oops", report.error.message
assert_equal "admin", report.context[:section]
assert_equal :warning, report.severity
assert_predicate report, :handled?
```

*Jean Boussier*
  • ActiveSupport::Deprecation behavior callbacks can now receive the deprecator instance as an argument. This makes it easier for such callbacks to change their behavior based on the deprecator's state. For example, based on the deprecator's debug flag.

    3-arity and splat-args callbacks such as the following will now be passed the deprecator instance as their third argument:

    • ->(message, callstack, deprecator) { ... }
    • ->(*args) { ... }
    • ->(message, *other_args) { ... }

    2-arity and 4-arity callbacks such as the following will continue to behave the same as before:

    • ->(message, callstack) { ... }
    • ->(message, callstack, deprecation_horizon, gem_name) { ... }
    • ->(message, callstack, *deprecation_details) { ... }

    Jonathan Hefner

  • ActiveSupport::Deprecation#disallowed_warnings now affects the instance on which it is configured.

    This means that individual ActiveSupport::Deprecation instances can be configured with their own disallowed warnings, and the global ActiveSupport::Deprecation.disallowed_warnings now only affects the global ActiveSupport::Deprecation.warn.

    Before

    ActiveSupport::Deprecation.disallowed_warnings = ["foo"]
    deprecator = ActiveSupport::Deprecation.new("2.0", "MyCoolGem")
    deprecator.disallowed_warnings = ["bar"]
    
    ActiveSupport::Deprecation.warn("foo") # => raise ActiveSupport::DeprecationException
    ActiveSupport::Deprecation.warn("bar") # => print "DEPRECATION WARNING: bar"
    deprecator.warn("foo")                 # => raise ActiveSupport::DeprecationException
    deprecator.warn("bar")                 # => print "DEPRECATION WARNING: bar"

    After

    ActiveSupport::Deprecation.disallowed_warnings = ["foo"]
    deprecator = ActiveSupport::Deprecation.new("2.0", "MyCoolGem")
    deprecator.disallowed_warnings = ["bar"]
    
    ActiveSupport::Deprecation.warn("foo") # => raise ActiveSupport::DeprecationException
    ActiveSupport::Deprecation.warn("bar") # => print "DEPRECATION WARNING: bar"
    deprecator.warn("foo")                 # => print "DEPRECATION WARNING: foo"
    deprecator.warn("bar")                 # => raise ActiveSupport::DeprecationException

    Note that global ActiveSupport::Deprecation methods such as ActiveSupport::Deprecation.warn and ActiveSupport::Deprecation.disallowed_warnings have been deprecated.

    Jonathan Hefner

  • Add italic and underline support to ActiveSupport::LogSubscriber#color

    Previously, only bold text was supported via a positional argument. This allows for bold, italic, and underline options to be specified for colored logs.

    info color("Hello world!", :red, bold: true, underline: true)

    Gannon McGibbon

  • Add String#downcase_first method.

    This method is the corollary of String#upcase_first.

    Mark Schneider

  • thread_mattr_accessor will call .dup.freeze on non-frozen default values.

    This provides a basic level of protection against different threads trying to mutate a shared default object.

    Jonathan Hefner

  • Add raise_on_invalid_cache_expiration_time config to ActiveSupport::Cache::Store

    Specifies if an ArgumentError should be raised if Rails.cache fetch or write are given an invalid expires_at or expires_in time.

    Options are true, and false. If false, the exception will be reported as handled and logged instead. Defaults to true if config.load_defaults >= 7.1.

    Trevor Turk

  • ActiveSupport::Cache:Store#fetch now passes an options accessor to the block.

    It makes possible to override cache options:

    Rails.cache.fetch("3rd-party-token") do |name, options|
      token = fetch_token_from_remote

set cache's TTL to match token's TTL

      options.expires_in = token.expires_in
      token
    end

*Andrii Gladkyi*, *Jean Boussier*
  • default option of thread_mattr_accessor now applies through inheritance and also across new threads.

    Previously, the default value provided was set only at the moment of defining the attribute writer, which would cause the attribute to be uninitialized in descendants and in other threads.

    Fixes #​43312.

    Thierry Deo

  • Redis cache store is now compatible with redis-rb 5.0.

    Jean Boussier

  • Add skip_nil: support to ActiveSupport::Cache::Store#fetch_multi.

    Daniel Alfaro

  • Add quarter method to date/time

    Matt Swanson

  • Fix NoMethodError on custom ActiveSupport::Deprecation behavior.

    ActiveSupport::Deprecation.behavior= was supposed to accept any object that responds to call, but in fact its internal implementation assumed that this object could respond to arity, so it was restricted to only Proc objects.

    This change removes this arity restriction of custom behaviors.

    Ryo Nakamura

  • Support :url_safe option for MessageEncryptor.

    The MessageEncryptor constructor now accepts a :url_safe option, similar to the MessageVerifier constructor. When enabled, this option ensures that messages use a URL-safe encoding.

    Jonathan Hefner

  • Add url_safe option to ActiveSupport::MessageVerifier initializer

    ActiveSupport::MessageVerifier.new now takes optional url_safe argument. It can generate URL-safe strings by passing url_safe: true.

    verifier = ActiveSupport::MessageVerifier.new(url_safe: true)
    message = verifier.generate(data) # => URL-safe string

    This option is false by default to be backwards compatible.

    Shouichi Kamiya

  • Enable connection pooling by default for MemCacheStore and RedisCacheStore.

    If you want to disable connection pooling, set :pool option to false when configuring the cache store:

    config.cache_store = :mem_cache_store, "cache.example.com", pool: false

    fatkodima

  • Add force: support to ActiveSupport::Cache::Store#fetch_multi.

    fatkodima

  • Deprecated :pool_size and :pool_timeout options for configuring connection pooling in cache stores.

    Use pool: true to enable pooling with default settings:

    config.cache_store = :redis_cache_store, pool: true

    Or pass individual options via :pool option:

    config.cache_store = :redis_cache_store, pool: { size: 10, timeout: 2 }

    fatkodima

  • Allow #increment and #decrement methods of ActiveSupport::Cache::Store subclasses to set new values.

    Previously incrementing or decrementing an unset key would fail and return nil. A default will now be assumed and the key will be created.

    Andrej Blagojević, Eugene Kenny

  • Add skip_nil: support to RedisCacheStore

    Joey Paris

  • ActiveSupport::Cache::MemoryStore#write(name, val, unless_exist:true) now correctly writes expired keys.

    Alan Savage

  • ActiveSupport::ErrorReporter now accepts and forward a source: parameter.

    This allow libraries to signal the origin of the errors, and reporters to easily ignore some sources.

    Jean Boussier

  • Fix and add protections for XSS in ActionView::Helpers and ERB::Util.

    Add the method ERB::Util.xml_name_escape to escape dangerous characters in names of tags and names of attributes, following the specification of XML.

    Álvaro Martín Fraguas

  • Respect ActiveSupport::Logger.new's :formatter keyword argument

    The stdlib Logger::new allows passing a :formatter keyword argument to set the logger's formatter. Previously ActiveSupport::Logger.new ignored that argument by always setting the formatter to an instance of ActiveSupport::Logger::SimpleFormatter.

    Steven Harman

  • Deprecate preserving the pre-Ruby 2.4 behavior of to_time

    With Ruby 2.4+ the default for +to_time+ changed from converting to the local system time to preserving the offset of the receiver. At the time Rails supported older versions of Ruby so a compatibility layer was added to assist in the migration process. From Rails 5.0 new applications have defaulted to the Ruby 2.4+ behavior and since Rails 7.0 now only supports Ruby 2.7+ this compatibility layer can be safely removed.

    To minimize any noise generated the deprecation warning only appears when the setting is configured to false as that is the only scenario where the removal of the compatibility layer has any effect.

    Andrew White

  • Pathname.blank? only returns true for Pathname.new("")

    Previously it would end up calling Pathname#empty? which returned true if the path existed and was an empty directory or file.

    That behavior was unlikely to be expected.

    Jean Boussier

  • Deprecate Notification::Event's #children and #parent_of?

    John Hawthorn

  • Change the default serializer of ActiveSupport::MessageVerifier from Marshal to ActiveSupport::JSON when using config.load_defaults 7.1.

    Messages serialized with Marshal can still be read, but new messages will be serialized with ActiveSupport::JSON. For more information, see https://guides.rubyonrails.org/v7.1/configuring.html#config-active-support-message-serializer.

    Saba Kiaei, David Buckley, and Jonathan Hefner

  • Change the default serializer of ActiveSupport::MessageEncryptor from Marshal to ActiveSupport::JSON when using config.load_defaults 7.1.

    Messages serialized with Marshal can still be read, but new messages will be serialized with ActiveSupport::JSON. For more information, see https://guides.rubyonrails.org/v7.1/configuring.html#config-active-support-message-serializer.

    Zack Deveau, Martin Gingras, and Jonathan Hefner

  • Add ActiveSupport::TestCase#stub_const to stub a constant for the duration of a yield.

    DHH

  • Fix ActiveSupport::EncryptedConfiguration to be compatible with Psych 4

    Stephen Sugden

  • Improve File.atomic_write error handling

    Daniel Pepper

  • Fix Class#descendants and DescendantsTracker#descendants compatibility with Ruby 3.1.

    The native Class#descendants was reverted prior to Ruby 3.1 release, but Class#subclasses was kept, breaking the feature detection.

    Jean Boussier

Active Model

  • Remove change in the typography of user facing error messages. For example, “can’t be blank” is again “can't be blank”.

    Rafael Mendonça França

  • Support composite identifiers in to_key

    to_key avoids wrapping #id value into an Array if #id already an array

    Nikita Vasilevsky

  • Add ActiveModel::Conversion.param_delimiter to configure delimiter being used in to_param

    Nikita Vasilevsky

  • undefine_attribute_methods undefines alias attribute methods along with attribute methods.

    Nikita Vasilevsky

  • Error.full_message now strips ":base" from the message.

    zzak

  • Add a load hook for ActiveModel::Model (named active_model) to match the load hook for ActiveRecord::Base and allow for overriding aspects of the ActiveModel::Model class.

    Lewis Buckley

  • Improve password length validation in ActiveModel::SecurePassword to consider byte size for BCrypt compatibility.

    The previous password length validation only considered the character count, which may not accurately reflect the 72-byte size limit imposed by BCrypt. This change updates the validation to consider both character count and byte size while keeping the character length validation in place.

    user = User.new(password: "a" * 73)  # 73 characters
    user.valid? # => false
    user.errors[:password] # => ["is too long"]
    
    user = User.new(password: "あ" * 25)  # 25 characters, 75 bytes
    user.valid? # => false
    user.errors[:password] # => ["is too long"]

    ChatGPT, Guillermo Iguaran

  • has_secure_password now generates an #{attribute}_salt method that returns the salt used to compute the password digest. The salt will change whenever the password is changed, so it can be used to create single-use password reset tokens with generates_token_for:

    class User < ActiveRecord::Base
      has_secure_password
    
      generates_token_for :password_reset, expires_in: 15.minutes do
        password_salt&.last(10)
      end
    end

    Lázaro Nixon

  • Improve typography of user facing error messages. In English contractions, the Unicode APOSTROPHE (U+0027) is now RIGHT SINGLE QUOTATION MARK (U+2019). For example, "can't be blank" is now "can’t be blank".

    Jon Dufresne

  • Add class to ActiveModel::MissingAttributeError error message.

    Show which class is missing the attribute in the error message:

    user = User.first
    user.pets.select(:id).first.user_id

=> ActiveModel::MissingAttributeError: missing attribute 'user_id' for Pet

```

*Petrik de Heus*
  • Raise NoMethodError in ActiveModel::Type::Value#as_json to avoid unpredictable results.

    Vasiliy Ermolovich

  • Custom attribute types that inherit from Active Model built-in types and do not override the serialize method will now benefit from an optimization when serializing attribute values for the database.

    For example, with a custom type like the following:

    class DowncasedString < ActiveModel::Type::String
      def cast(value)
        super&.downcase
      end
    end
    
    ActiveRecord::Type.register(:downcased_string, DowncasedString)
    
    class User < ActiveRecord::Base
      attribute :email, :downcased_string
    end
    
    user = User.new(email: "FooBar@example.com")

    Serializing the email attribute for the database will be roughly twice as fast. More expensive cast operations will likely see greater improvements.

    Jonathan Hefner

  • has_secure_password now supports password challenges via a password_challenge accessor and validation.

    A password challenge is a safeguard to verify that the current user is actually the password owner. It can be used when changing sensitive model fields, such as the password itself. It is different than a password confirmation, which is used to prevent password typos.

    When password_challenge is set, the validation checks that the value's digest matches the currently persisted password_digest (i.e. password_digest_was).

    This allows a password challenge to be done as part of a typical update call, just like a password confirmation. It also allows a password challenge error to be handled in the same way as other validation errors.

    For example, in the controller, instead of:

    password_params = params.require(:password).permit(
      :password_challenge,
      :password,
      :password_confirmation,
    )
    
    password_challenge = password_params.delete(:password_challenge)
    @&#8203;password_challenge_failed = !current_user.authenticate(password_challenge)
    
    if !@&#8203;password_challenge_failed && current_user.update(password_params)

...

end
```

You can now write:

```ruby
password_params = params.require(:password).permit(
  :password_challenge,
  :password,
  :password_confirmation,
).with_defaults(password_challenge: "")

if current_user.update(password_params)

...

end
```

And, in the view, instead of checking `@password_challenge_failed`, you can
render an error for the `password_challenge` field just as you would for
other form fields, including utilizing `config.action_view.field_error_proc`.

*Jonathan Hefner*
  • Support infinite ranges for LengthValidators :in/:within options

    validates_length_of :first_name, in: ..30

    fatkodima

  • Add support for beginless ranges to inclusivity/exclusivity validators:

    validates_inclusion_of :birth_date, in: -> { (..Date.today) }
    validates_exclusion_of :birth_date, in: -> { (..Date.today) }

    Bo Jeanes

  • Make validators accept lambdas without record argument

Before

validates_comparison_of :birth_date, less_than_or_equal_to: ->(_record) { Date.today }

After

validates_comparison_of :birth_date, less_than_or_equal_to: -> { Date.today }
```

*fatkodima*
  • Fix casting long strings to Date, Time or DateTime

    fatkodima

  • Use different cache namespace for proxy calls

    Models can currently have different attribute bodies for the same method names, leading to conflicts. Adding a new namespace :active_model_proxy fixes the issue.

    Chris Salzberg

Active Record

  • Remove -shm and -wal SQLite files when rails db:drop is run.

    Niklas Häusele

  • Revert the change to raise an ArgumentError when #accepts_nested_attributes_for is declared more than once for an association in the same class.

    The reverted behavior broke the case where the #accepts_nested_attributes_for was defined in a concern and where overridden in the class that included the concern.

    Rafael Mendonça França

  • Better naming for unique constraints support.

    Naming unique keys leads to misunderstanding it's a short-hand of unique indexes. Just naming it unique constraints is not misleading.

    In Rails 7.1.0.beta1 or before:

    add_unique_key :sections, [:position], deferrable: :deferred, name: "unique_section_position"
    remove_unique_key :sections, name: "unique_section_position"

    Now:

    add_unique_constraint :sections, [:position], deferrable: :deferred, name: "unique_section_position"
    remove_unique_constraint :sections, name: "unique_section_position"

    Ryuta Kamizono

  • 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

  • Performance tune the SQLite3 adapter connection configuration

    For Rails applications, the Write-Ahead-Log in normal syncing mode with a capped journal size, a healthy shared memory buffer and a shared cache will perform, on average, 2× better.

    Stephen Margheim

  • Allow SQLite3 busy_handler to be configured with simple max number of retries

    Retrying busy connections without delay is a preferred practice for performance-sensitive applications. Add support for a database.yml retries integer, which is used in a simple busy_handler function to retry busy connections without exponential backoff up to the max number of retries.

    Stephen Margheim

  • The SQLite3 adapter now supports supports_insert_returning?

    Implementing the full supports_insert_returning? contract means the SQLite3 adapter supports auto-populated columns (#​48241) as well as custom primary keys.

    Stephen Margheim

  • Ensure the SQLite3 adapter handles default functions with the || concatenation operator

    Previously, this default function would produce the static string "'Ruby ' || 'on ' || 'Rails'". Now, the adapter will appropriately receive and use "Ruby on Rails".

    change_column_default "test_models", "ruby_on_rails", -> { "('Ruby ' || 'on ' || 'Rails')" }

    Stephen Margheim

  • Dump PostgreSQL schemas as part of the schema dump.

    Lachlan Sylvester

  • Encryption now supports support_unencrypted_data being set per-attribute.

    You can now opt out of support_unencrypted_data on a specific encrypted attribute. This only has an effect if ActiveRecord::Encryption.config.support_unencrypted_data == true.

    class User < ActiveRecord::Base
      encrypts :name, deterministic: true, support_unencrypted_data: false
      encrypts :email, deterministic: true
    end

    Alex Ghiculescu

  • Add instrumentation for Active Record transactions

    Allows subscribing to transaction events for tracking/instrumentation. The event payload contains the connection and the outcome (commit, rollback, restart, incomplete), as well as timing details.

    ActiveSupport::Notifications.subscribe("transaction.active_record") do |event|
      puts "Transaction event occurred!"
      connection = event.payload[:connection]
      puts "Connection: #{connection.inspect}"
    end

    Daniel Colson, Ian Candy

  • Support composite foreign keys via migration helpers.

Assuming "carts" table has "(shop_id, user_id)" as a primary key.

add_foreign_key(:orders, :carts, primary_key: [:shop_id, :user_id])

remove_foreign_key(:orders, :carts, primary_key: [:shop_id, :user_id])
foreign_key_exists?(:orders, :carts, primary_key: [:shop_id, :user_id])
```

*fatkodima*
  • Adds support for if_not_exists when adding a check constraint.

    add_check_constraint :posts, "post_type IN ('blog', 'comment', 'share')", if_not_exists: true

    Cody Cutrer

  • Raise an ArgumentError when #accepts_nested_attributes_for is declared more than once for an association in the same class. Previously, the last declaration would silently override the previous one. Overriding in a subclass is still allowed.

    Joshua Young

  • Deprecate rewhere argument on #merge.

    The rewhere argument on #mergeis deprecated without replacement and will be removed in Rails 7.2.

    Adam Hess

  • Fix unscope is not working in specific case

    Before:

    Post.where(id: 1...3).unscope(where: :id).to_sql # "SELECT `posts`.* FROM `posts` WHERE `posts`.`id` >= 1 AND `posts`.`id` < 3"
    

    After:

    Post.where(id: 1...3).unscope(where: :id).to_sql # "SELECT `posts`.* FROM `posts`"

    Fixes #​48094.

    Kazuya Hatanaka

  • Change has_secure_token default to on: :initialize

    Change the new default value from on: :create to on: :initialize

    Can be controlled by the config.active_record.generate_secure_token_on configuration:

    config.active_record.generate_secure_token_on = :create

    Sean Doyle

  • Fix change_column not setting precision: 6 on datetime columns when using 7.0+ Migrations and SQLite.

    Hartley McGuire

  • Support composite identifiers in to_key

    to_key avoids wrapping #id value into an Array if #id already an array

    Nikita Vasilevsky

  • Add validation option for enum

    class Contract < ApplicationRecord
      enum :status, %w[in_progress completed], validate: true
    end
    Contract.new(status: "unknown").valid? # => false
    Contract.new(status: nil).valid? # => false
    Contract.new(status: "completed").valid? # => true
    
    class Contract < ApplicationRecord
      enum :status, %w[in_progress completed], validate: { allow_nil: true }
    end
    Contract.new(status: "unknown").valid? # => false
    Contract.new(status: nil).valid? # => true
    Contract.new(status: "completed").valid? # => true

    Edem Topuzov, Ryuta Kamizono

  • Allow batching methods to use already loaded relation if available

    Calling batch methods on already loaded relations will use the records previously loaded instead of retrieving them from the database again.

    Adam Hess

  • Deprecate read_attribute(:id) returning the primary key if the primary key is not :id.

    Starting in Rails 7.2, read_attribute(:id) will return the value of the id column, regardless of the model's primary key. To retrieve the value of the primary key, use #id instead. read_attribute(:id) for composite primary key models will now return the value of the id column.

    Adrianna Chang

  • Fix change_table setting datetime precision for 6.1 Migrations

    Hartley McGuire

  • Fix change_column setting datetime precision for 6.1 Migrations

    Hartley McGuire

  • Add ActiveRecord::Base#id_value alias to access the raw value of a record's id column.

    This alias is only provided for models that declare an :id column.

    Adrianna Chang

  • Fix previous change tracking for ActiveRecord::Store when using a column with JSON structured database type

    Before, the methods to access the changes made during the last save #saved_change_to_key?, #saved_change_to_key, and #key_before_last_save did not work if the store was defined as a store_accessor on a column with a JSON structured database type

    Robert DiMartino

  • Fully support NULLS [NOT] DISTINCT for PostgreSQL 15+ indexes.

    Previous work was done to allow the index to be created in a migration, but it was not supported in schema.rb. Additionally, the matching for NULLS [NOT] DISTINCT was not in the correct order, which could have resulted in inconsistent schema detection.

    Gregory Jones

  • Allow escaping of literal colon characters in sanitize_sql_* methods when named bind variables are used

    Justin Bull

  • Fix #previously_new_record? to return true for destroyed records.

    Before, if a record was created and then destroyed, #previously_new_record? would return true. Now, any UPDATE or DELETE to a record is considered a change, and will result in #previously_new_record? returning false.

    Adrianna Chang

  • Specify callback in has_secure_token

    class User < ApplicationRecord
      has_secure_token on: :initialize
    end
    
    User.new.token # => "abc123...."

    Sean Doyle

  • Fix incrementation of in memory counter caches when associations overlap

    When two associations had a similarly named counter cache column, Active Record could sometime increment the wrong one.

    Jacopo Beschi, Jean Boussier

  • Don't show secrets for Active Record's Cipher::Aes256Gcm#inspect.

    Before:

    ActiveRecord::Encryption::Cipher::Aes256Gcm.new(secret).inspect
    "#<ActiveRecord::Encryption::Cipher::Aes256Gcm:0x0000000104888038 ... @&#8203;secret=\"\\xAF\\bFh]LV}q\\nl\\xB2U\\xB3 ... >"

    After:

    ActiveRecord::Encryption::Cipher::Aes256Gcm(secret).inspect
    "#<ActiveRecord::Encryption::Cipher::Aes256Gcm:0x0000000104888038>"

    Petrik de Heus

  • Bring back the historical behavior of committing transaction on non-local return.

    Model.transaction do
      model.save
      return
      other_model.save # not executed
    end

    Historically only raised errors would trigger a rollback, but in Ruby 2.3, the timeout library started using throw to interrupt execution which had the adverse effect of committing open transactions.

    To solve this, in Active Record 6.1 the behavior was changed to instead rollback the transaction as it was safer than to potentially commit an incomplete transaction.

    Using return, break or throw inside a transaction block was essentially deprecated from Rails 6.1 onwards.

    However with the release of timeout 0.4.0, Timeout.timeout now raises an error again, and Active Record is able to return to its original, less surprising, behavior.

    This historical behavior can now be opt-ed in via:

    Rails.application.config.active_record.commit_transaction_on_non_local_return = true

    And is the default for new applications created in Rails 7.1.

    Jean Boussier

  • Deprecate name argument on #remove_connection.

    The name argument is deprecated on #remove_connection without replacement. #remove_connection should be called directly on the class that established the connection.

    Eileen M. Uchitelle

  • Fix has_one through singular building with inverse.

    Allows building of records from an association with a has_one through a singular association with inverse. For belongs_to through associations, linking the foreign key to the primary key model isn't needed. For has_one, we cannot build records due to the association not being mutable.

    Gannon McGibbon

  • Disable database prepared statements when query logs are enabled

    Prepared Statements and Query Logs are incompatible features due to query logs making every query unique.

    zzak, Jean Boussier

  • Support decrypting data encrypted non-deterministically with a SHA1 hash digest.

    This adds a new Active Record encryption option to support decrypting data encrypted non-deterministically with a SHA1 hash digest:

    Rails.application.config.active_record.encryption.support_sha1_for_non_deterministic_encryption = true

    The new option addresses a problem when upgrading from 7.0 to 7.1. Due to a bug in how Active Record Encryption was getting initialized, the key provider used for non-deterministic encryption were using SHA-1 as its digest class, instead of the one configured globally by Rails via Rails.application.config.active_support.key_generator_hash_digest_class.

    Cadu Ribeiro and Jorge Manrubia

  • Added PostgreSQL migration commands for enum rename, add value, and rename value.

    rename_enum and rename_enum_value are reversible. Due to Postgres limitation, add_enum_value is not reversible since you cannot delete enum values. As an alternative you should drop and recreate the enum entirely.

    rename_enum :article_status, to: :article_state
    add_enum_value :article_state, "archived" # will be at the end of existing values
    add_enum_value :article_state, "in review", before: "published"
    add_enum_value :article_state, "approved", after: "in review"
    rename_enum_value :article_state, from: "archived", to: "deleted"

    Ray Faddis

  • Allow composite primary key to be derived from schema

    Booting an application with a schema that contains composite primary keys will not issue warning and won't nilify the ActiveRecord::Base#primary_key value anymore.

    Given a travel_routes table definition and a TravelRoute model like:

    create_table :travel_routes, primary_key: [:origin, :destination], force: true do |t|
      t.string :origin
      t.string :destination
    end
    
    class TravelRoute < ActiveRecord::Base; end

    The TravelRoute.primary_key value will be automatically derived to ["origin", "destination"]

    Nikita Vasilevsky

  • Include the connection_pool with exceptions raised from an adapter.

    The connection_pool provides added context such as the connection used that led to the exception as well as which role and shard.

    Luan Vieira

  • Support multiple column ordering for find_each, find_in_batches and in_batches.

    When find_each/find_in_batches/in_batches are performed on a table with composite primary keys, ascending or descending order can be selected for each key.

    Person.find_each(order: [:desc, :asc]) do |person|
      person.party_all_night!
    end

    Takuya Kurimoto

  • Fix where on association with has_one/has_many polymorphic relations.

    Before:

    Treasure.where(price_estimates: PriceEstimate.all)
    #=> SELECT (...) WHERE "treasures"."id" IN (SELECT "price_estimates"."estimate_of_id" FROM "price_estimates")

    Later:

    Treasure.where(price_estimates: PriceEstimate.all)
    #=> SELECT (...) WHERE "treasures"."id" IN (SELECT "price_estimates"."estimate_of_id" FROM "price_estimates" WHERE "price_estimates"."estimate_of_type" = 'Treasure')

    Lázaro Nixon

  • Assign auto populated columns on Active Record record creation.

    Changes record creation logic to allow for the auto_increment column to be assigned immediately after creation regardless of it's relation to the model's primary key.

    The PostgreSQL adapter benefits the most from the change allowing for any number of auto-populated columns to be assigned on the object immediately after row insertion utilizing the RETURNING statement.

    Nikita Vasilevsky

  • Use the first key in the shards hash from connected_to for the default_shard.

    Some applications may not want to use :default as a shard name in their connection model. Unfortunately Active Record expects there to be a :default shard because it must assume a shard to get the right connection from the pool manager. Rather than force applications to manually set this, connects_to can infer the default shard name from the hash of shards and will now assume that the first shard is your default.

    For example if your model looked like this:

    class ShardRecord < ApplicationRecord
      self.abstract_class = true
    
      connects_to shards: {
        shard_one: { writing: :shard_one },
        shard_two: { writing: :shard_two }
      }

    Then the default_shard for this class would be set to shard_one.

    Fixes: #​45390

    Eileen M. Uchitelle

  • Fix mutation detection for serialized attributes backed by binary columns.

    Jean Boussier

  • Add ActiveRecord.disconnect_all! method to immediately close all connections from all pools.

    Jean Boussier

  • Discard connections which may have been left in a transaction.

    There are cases where, due to an error, within_new_transaction may unexpectedly leave a connection in an open transaction. In these cases the connection may be reused, and the following may occur:

    • Writes appear to fail when they actually succeed.
    • Writes appear to succeed when they actually fail.
    • Reads return stale or uncommitted data.

    Previously, the following case was detected:

    • An error is encountered during the transaction, then another error is encountered while attempting to roll it back.

    Now, the following additional cases are detected:

    • An error is encountered just after successfully beginning a transaction.
    • An error is encountered while committing a transaction, then another error is encountered while attempting to roll it back.
    • An error is encountered while rolling back a transaction.

    Nick Dower

  • Active Record query cache now evicts least recently used entries

    By default it only keeps the 100 most recently used queries.

    The cache size can be configured via database.yml

    development:
      adapter: mysql2
      query_cache: 200

    It can also be entirely disabled:

    development:
      adapter: mysql2
      query_cache: false

    Jean Boussier

  • Deprecate check_pending! in favor of check_all_pending!.

    check_pending! will only check for pending migrations on the current database connection or the one passed in. This has been deprecated in favor of check_all_pending! which will find all pending migrations for the database configurations in a given environment.

    Eileen M. Uchitelle

  • Make increment_counter/decrement_counter accept an amount argument

    Post.increment_counter(:comments_count, 5, by: 3)

    fatkodima

  • Add support for Array#intersect? to ActiveRecord::Relation.

    Array#intersect? is only available on Ruby 3.1 or later.

    This allows the Rubocop Style/ArrayIntersect cop to work with ActiveRecord::Relation objects.

    John Harry Kelly

  • The deferrable foreign key can be passed to t.references.

    Hiroyuki Ishii

  • Deprecate deferrable: true option of add_foreign_key.

    deferrable: true is deprecated in favor of deferrable: :immediate, and will be removed in Rails 7.2.

    Because deferrable: true and deferrable: :deferred are hard to understand. Both true and :deferred are truthy values. This behavior is the same as the deferrable option of the add_unique_key method, added in #​46192.

    Hiroyuki Ishii

  • AbstractAdapter#execute and #exec_query now clear the query cache

    If you need to perform a read only SQL query without clearing the query cache, use AbstractAdapter#select_all.

    Jean Boussier

  • Make .joins / .left_outer_joins work with CTEs.

    For example:

    Post
     .with(commented_posts: Comment.select(:post_id).distinct)
     .joins(:commented_posts)
    #=> WITH (...) SELECT ... INNER JOIN commented_posts on posts.id = commented_posts.post_id

    Vladimir Dementyev

  • Add a load hook for ActiveRecord::ConnectionAdapters::Mysql2Adapter (named active_record_mysql2adapter) to allow for overriding aspects of the ActiveRecord::ConnectionAdapters::Mysql2Adapter class. This makes Mysql2Adapter consistent with PostgreSQLAdapter and SQLite3Adapter that already have load hooks.

    fatkodima

  • Introduce adapter for Trilogy database client

    Trilogy is a MySQL-compatible database client. Rails applications can use Trilogy by configuring their config/database.yml:

    development:
    adapter: trilogy
    database: blog_development
    pool: 5

    Or by using the DATABASE_URL environment variable:

    ENV['DATABASE_URL'] # => "trilogy://localhost/blog_development?pool=5"

    Adrianna Chang

  • after_commit callbacks defined on models now execute in the correct order.

    class User < ActiveRecord::Base
      after_commit { puts("this gets called first") }
      after_commit { puts("this gets called second") }
    end

    Previously, the callbacks executed in the reverse order. To opt in to the new behaviour:

    config.active_record.run_after_transaction_callbacks_in_order_defined = true

    This is the default for new apps.

    Alex Ghiculescu

  • Infer foreign_key when inverse_of is present on has_one and has_many associations.

    has_many :citations, foreign_key: "book1_id", inverse_of: :book

    can be simplified to

    has_many :citations, inverse_of: :book

    and the foreign_key will be read from the corresponding belongs_to association.

    Daniel Whitney

  • Limit max length of auto generated index names

    Auto generated index names are now limited to 62 bytes, which fits within the default index name length limits for MySQL, Postgres and SQLite.

    Any index name over the limit will fallback to the new short format.

    Before (too long):

    index_testings_on_foo_and_bar_and_first_name_and_last_name_and_administrator

    After (short format):

    idx_on_foo_bar_first_name_last_name_administrator_5939248142

    The short format includes a hash to ensure the name is unique database-wide.

    Mike Coutermarsh

  • Introduce a more stable and optimized Marshal serializer for Active Record models.

    Can be enabled with config.active_record.marshalling_format_version = 7.1.

    Jean Boussier

  • Allow specifying where clauses with column-tuple syntax.

    Querying through #where now accepts a new tuple-syntax which accepts, as a key, an array of columns and, as a value, an array of corresponding tuples. The key specifies a list of columns, while the value is an array of ordered-tuples that conform to the column list.

    For instance:

Cpk::Book => Cpk::Book(author_id: integer, number: integer, title: string, revision: integer)

Cpk::Book.primary_key => ["author_id", "number"]

book = Cpk::Book.create!(author_id: 1, number: 1)
Cpk::Book.where(Cpk::Book.primary_key => [[1, 2]]) # => [book]

Topic => Topic(id: integer, title: string, author_name: string...)

Topic.where([:title, :author_name] => [["The Alchemist", "Paulo Coelho"], ["Harry Potter", "J.K Rowling"]])
```

*Paarth Madan*
  • Allow warning codes to be ignore when reporting SQL warnings.

    Active Record config that can ignore warning codes

Configure allowlist of warnings that should always be ignored

config.active_record.db_warnings_ignore = [
  "1062", # MySQL Error 1062: Duplicate entry
]
```

This is supported for the MySQL and PostgreSQL adapters.

*Nick Borromeo*
  • Introduce :active_record_fixtures lazy load hook.

    Hooks defined with this name will be run whenever TestFixtures is included in a class.

    ActiveSupport.on_load(:active_record_fixtures) do
      self.fixture_paths << "test/fixtures"
    end
    
    klass = Class.new
    klass.include(ActiveRecord::TestFixtures)
    
    klass.fixture_paths # => ["test/fixtures"]

    Andrew Novoselac

  • Introduce TestFixtures#fixture_paths.

    Multiple fixture paths can now be specified using the #fixture_paths accessor. Apps will continue to have test/fixtures as their one fixture path by default, but additional fixture paths can be specified.

    ActiveSupport::TestCase.fixture_paths << "component1/test/fixtures"
    ActiveSupport::TestCase.fixture_paths << "component2/test/fixtures"

    TestFixtures#fixture_path is now deprecated.

    Andrew Novoselac

  • Adds support for deferrable exclude constraints in PostgreSQL.

    By default, exclude constraints in PostgreSQL are checked after each statement. This works for most use cases, but becomes a major limitation when replacing records with overlapping ranges by using multiple statements.

    exclusion_constraint :users, "daterange(valid_from, valid_to) WITH &&", deferrable: :immediate

    Passing deferrable: :immediate checks constraint after each statement, but allows manually deferring the check using SET CONSTRAINTS ALL DEFERRED within a transaction. This will cause the excludes to be checked after the transaction.

    It's also possible to change the default behavior from an immediate check (after the statement), to a deferred check (after the transaction):

    exclusion_constraint :users, "daterange(valid_from, valid_to) WITH &&", deferrable: :deferred

    Hiroyuki Ishii

  • Respect foreign_type option to delegated_type for {role}_class method.

    Usage of delegated_type with non-conventional {role}_type column names can now be specified with foreign_type option. This option is the same as foreign_type as forwarded to the underlying belongs_to association that delegated_type wraps.

    Jason Karns

  • Add support for unique constraints (PostgreSQL-only).

    add_unique_key :sections, [:position], deferrable: :deferred, name: "unique_section_position"
    remove_unique_key :sections, name: "unique_section_position"

    See PostgreSQL's Unique Constraints documentation for more on unique constraints.

    By default, unique constraints in PostgreSQL are checked after each statement. This works for most use cases, but becomes a major limitation when replacing records with unique column by using multiple statements.

    An example of swapping unique columns between records.

position is unique column

old_item = Item.create!(position: 1)
new_item = Item.create!(position: 2)

Item.transaction do
  old_item.update!(position: 2)
  new_item.update!(position: 1)
end
```

Using the default behavior, the transaction would fail when executing the
first `UPDATE` statement.

By passing the `:deferrable` option to the `add_unique_key` statement in
migrations, it's possible to defer this check.

```ruby
add_unique_key :items, [:position], deferrable: :immediate
```

Passing `deferrable: :immediate` does not change the behaviour of the previous example,
but allows manually deferring the check using `SET CONSTRAINTS ALL DEFERRED` within a transaction.
This will cause the unique constraints to be checked after the transaction.

It's also possible to adjust the default behavior from an immediate
check (after the statement), to a deferred check (after the transaction):

```ruby
add_unique_key :items, [:position], deferrable: :deferred
```

If you want to change an existing unique index to deferrable, you can use :using_index
to create deferrable unique constraints.

```ruby
add_unique_key :items, deferrable: :deferred, using_index: "index_items_on_position"
```

*Hiroyuki Ishii*
  • Remove deprecated Tasks::DatabaseTasks.schema_file_type.

    Rafael Mendonça França

  • Remove deprecated config.active_record.partial_writes.

    Rafael Mendonça França

  • Remove deprecated ActiveRecord::Base config accessors.

    Rafael Mendonça França

  • Remove the :include_replicas argument from configs_for. Use :include_hidden argument instead.

    Eileen M. Uchitelle

  • Allow applications to lookup a config via a custom hash key.

    If you have registered a custom config or want to find configs where the hash matches a specific key, now you can pass config_key to configs_for. For example if you have a db_config with the key vitess you can look up a database configuration hash by matching that key.

    ActiveRecord::Base.configurations.configs_for(env_name: "development", name: "primary", config_key: :vitess)
    ActiveRecord::Base.configurations.configs_for(env_name: "development", config_key: :vitess)

    Eileen M. Uchitelle

  • Allow applications to register a custom database configuration handler.

    Adds a mechanism for registering a custom handler for cases where you want database configurations to respond to custom methods. This is useful for non-Rails database adapters or tools like Vitess that you may want to configure differently from a standard HashConfig or UrlConfig.

    Given the following database YAML we want the animals db to create a CustomConfig object instead while the primary database will be a UrlConfig:

    development:
      primary:
        url: postgres://localhost/primary
      animals:
        url: postgres://localhost/animals
        custom_config:
          sharded: 1

    To register a custom handler first make a class that has your custom methods:

    class CustomConfig < ActiveRecord::DatabaseConfigurations::UrlConfig
      def sharded?
        custom_config.fetch("sharded", false)
      end
    
      private
        def custom_config
          configuration_hash.fetch(:custom_config)
        end
    end

    Then register the config in an initializer:

    ActiveRecord::DatabaseConfigurations.register_db_config_handler do |env_name, name, url, config|
      next unless config.key?(:custom_config)
      CustomConfig.new(env_name, name, url, config)
    end

    When the application is booted, configuration hashes with the :custom_config key will be CustomConfig objects and respond to sharded?. Applications must handle the condition in which Active Record should use their custom handler.

    Eileen M. Uchitelle and John Crepezzi

  • ActiveRecord::Base.serialize no longer uses YAML by default.

    YAML isn't particularly performant and can lead to security issues if not used carefully.

    Unfortunately there isn't really any good serializers in Ruby's stdlib to replace it.

    The obvious choice would be JSON, which is a fine format for this use case, however the JSON serializer in Ruby's stdlib isn't strict enough, as it fallback to casting unknown types to strings, which could lead to corrupted data.

    Some third party JSON libraries like Oj have a suitable strict mode.

    So it's preferable that users choose a serializer based on their own constraints.

    The original default can be restored by setting config.active_record.default_column_serializer = YAML.

    Jean Boussier

  • ActiveRecord::Base.serialize signature changed.

    Rather than a single positional argument that accepts two possible types of values, serialize now accepts two distinct keyword arguments.

    Before:

    serialize :content, JSON
    serialize :backtrace, Array

    After:

    serialize :content, coder: JSON
    serialize :backtrace, type: Array

    Jean Boussier

  • YAML columns use YAML.safe_dump if available.

    As of psych 5.1.0, YAML.safe_dump can now apply the same permitted types restrictions than YAML.safe_load.

    It's preferable to ensure the payload only use allowed types when we first try to serialize it, otherwise you may end up with invalid records in the database.

    Jean Boussier

  • ActiveRecord::QueryLogs better handle broken encoding.

    It's not uncommon when building queries with BLOB fields to contain binary data. Unless the call carefully encode the string in ASCII-8BIT it generally end up being encoded in UTF-8, and QueryLogs would end up failing on it.

    ActiveRecord::QueryLogs no longer depend on the query to be properly encoded.

    Jean Boussier

  • Fix a bug where ActiveRecord::Generators::ModelGenerator would not respect create_table_migration template overrides.

    rails g model create_books title:string content:text

    will now read from the create_table_migration.rb.tt template in the following locations in order:

    lib/templates/active_record/model/create_table_migration.rb
    lib/templates/active_record/migration/create_table_migration.rb

    Spencer Neste

  • ActiveRecord::Relation#explain now accepts options.

    For databases and adapters which support them (currently PostgreSQL and MySQL), options can be passed to explain to provide more detailed query plan analysis:

    Customer.where(id: 1).joins(:orders).explain(:analyze, :verbose)

    Reid Lynch

  • Multiple Arel::Nodes::SqlLiteral nodes can now be added together to form Arel::Nodes::Fragments nodes. This allows joining several pieces of SQL.

    Matthew Draper, Ole Friis

  • ActiveRecord::Base#signed_id raises if called on a new record.

    Previously it would return an ID that was not usable, since it was based on id = nil.

    Alex Ghiculescu

  • Allow SQL warnings to be reported.

    Active Record configs can be set to enable SQL warning reporting.

Configure action to take when SQL query produces warning

config.active_record.db_warnings_action = :raise

Configure allowlist of warnings that should always be ignored

config.active_record.db_warnings_ignore = [
  /Invalid utf8mb4 character string/,
  "An exact warning message",
]
```

This is supported for the MySQL and PostgreSQL adapters.

*Adrianna Chang*, *Paarth Madan*
  • Add #regroup query method as a short-hand for .unscope(:group).group(fields)

    Example:

    Post.group(:title).regroup(:author)

SELECT posts.* FROM posts GROUP BY posts.author

```

*Danielius Visockas*
  • PostgreSQL adapter method enable_extension now allows parameter to be [schema_name.]<extension_name> if the extension must be installed on another schema.

    Example: enable_extension('heroku_ext.hstore')

    Leonardo Luarte

  • Add :include option to add_index.

    Add support for including non-key columns in indexes for PostgreSQL with the INCLUDE parameter.

    add_index(:users, :email, include: [:id, :created_at])

    will result in:

    CREATE INDEX index_users_on_email USING btree (email) INCLUDE (id, created_at)

    Steve Abrams

  • ActiveRecord::Relation’s #any?, #none?, and #one? methods take an optional pattern argument, more closely matching their Enumerable equivalents.

    George Claghorn

  • Add ActiveRecord::Base.normalizes for declaring attribute normalizations.

    An attribute normalization is applied when the attribute is assigned or updated, and the normalized value will be persisted to the database. The normalization is also applied to the corresponding keyword argument of query methods, allowing records to be queried using unnormalized values.

    For example:

    class User < ActiveRecord::Base
      normalizes :email, with: -> email { email.strip.downcase }
      normalizes :phone, with: -> phone { phone.delete("^0-9").delete_prefix("1") }
    end
    
    user = User.create(email: " CRUISE-CONTROL@EXAMPLE.COM\n")
    user.email                  # => "cruise-control@example.com"
    
    user = User.find_by(email: "\tCRUISE-CONTROL@EXAMPLE.COM ")
    user.email                  # => "cruise-control@example.com"
    user.email_before_type_cast # => "cruise-control@example.com"
    
    User.where(email: "\tCRUISE-CONTROL@EXAMPLE.COM ").count         # => 1
    User.where(["email = ?", "\tCRUISE-CONTROL@EXAMPLE.COM "]).count # => 0
    
    User.exists?(email: "\tCRUISE-CONTROL@EXAMPLE.COM ")         # => true
    User.exists?(["email = ?", "\tCRUISE-CONTROL@EXAMPLE.COM "]) # => false
    
    User.normalize_value_for(:phone, "+1 (555) 867-5309") # => "5558675309"

    Jonathan Hefner

  • Hide changes to before_committed! callback behaviour behind flag.

    In #​46525, behavior around before_committed! callbacks was changed so that callbacks would run on every enrolled record in a transaction, not just the first copy of a record. This change in behavior is now controlled by a configuration option, config.active_record.before_committed_on_all_records. It will be enabled by default on Rails 7.1.

    Adrianna Chang

  • The namespaced_controller Query Log tag now matches the controller format

    For example, a request processed by NameSpaced::UsersController will now log as:

    :controller # "users"
    :namespaced_controller # "name_spaced/users"

    Alex Ghiculescu

  • Return only unique ids from ActiveRecord::Calculations#ids

    Updated ActiveRecord::Calculations#ids to only return the unique ids of the base model when using eager_load, preload and includes.

    Post.find_by(id: 1).comments.count

=> 5

Post.includes(:comments).where(id: 1).pluck(:id)

=> [1, 1, 1, 1, 1]

Post.includes(:comments).where(id: 1).ids

=> [1]

```

*Joshua Young*
  • Stop using LOWER() for case-insensitive queries on citext columns

    Previously, LOWER() was added for e.g. uniqueness validations with case_sensitive: false. It wasn't mentioned in the documentation that the index without LOWER() wouldn't be used in this case.

    Phil Pirozhkov

  • Extract #sync_timezone_changes method in AbstractMysqlAdapter to enable subclasses to sync database timezone changes without overriding #raw_execute.

    Adrianna Chang, Paarth Madan

  • Do not write additional new lines when dumping sql migration versions

    This change updates the insert_versions_sql function so that the database insert string containing the current database migration versions does not end with two additional new lines.

    Misha Schwartz

  • Fix composed_of value freezing and duplication.

    Previously composite values exhibited two confusing behaviors:

    • When reading a compositve value it'd NOT be frozen, allowing it to get out of sync with its underlying database columns.
    • When writing a compositve value the argument would be frozen, potentially confusing the caller.

    Currently, composite values instantiated based on database columns are frozen (addressing the first issue) and assigned compositve values are duplicated and the duplicate is frozen (addressing the second issue).

    Greg Navis

  • Fix redundant updates to the column insensitivity cache

    Fixed redundant queries checking column capability for insensitive comparison.

    Phil Pirozhkov

  • Allow disabling methods generated by ActiveRecord.enum.

    Alfred Dominic

  • Avoid validating belongs_to association if it has not changed.

    Previously, when updating a record, Active Record will perform an extra query to check for the presence of belongs_to associations (if the presence is configured to be mandatory), even if that attribute hasn't changed.

    Currently, only belongs_to-related columns are checked for presence. It is possible to have orphaned records with this approach. To avoid this problem, you need to use a foreign key.

    This behavior can be controlled by configuration:

    config.active_record.belongs_to_required_validates_foreign_key = false

    and will be disabled by default with config.load_defaults 7.1.

    fatkodima

  • has_one and belongs_to associations now define a reset_association method on the owner model (where association is the name of the association). This method unloads the cached associate record, if any, and causes the next access to query it from the database.

    George Claghorn

  • Allow per attribute setting of YAML permitted classes (safe load) and unsafe load.

    Carlos Palhares

  • Add a build persistence method

    Provides a wrapper for new, to provide feature parity with creates ability to create multiple records from an array of hashes, using the same notation as the build method on associations.

    Sean Denny

  • Raise on assignment to readonly attributes

    class Post < ActiveRecord::Base
      attr_readonly :content
    end
    Post.create!(content: "cannot be updated")
    post.content # "cannot be updated"
    post.content = "something else" # => ActiveRecord::ReadonlyAttributeError

    Previously, assignment would succeed but silently not write to the database.

    This behavior can be controlled by configuration:

    config.active_record.raise_on_assign_to_attr_readonly = true

    and will be enabled by default with config.load_defaults 7.1.

    Alex Ghiculescu, Hartley McGuire

  • Allow unscoping of preload and eager_load associations

    Added the ability to unscope preload and eager_load associations just like includes, joins, etc. See ActiveRecord::QueryMethods::VALID_UNSCOPING_VALUES for the full list of supported unscopable scopes.

    query.unscope(:eager_load, :preload).group(:id).select(:id)

    David Morehouse

  • Add automatic filtering of encrypted attributes on inspect

    This feature is enabled by default but can be disabled with

    config.active_record.encryption.add_to_filter_parameters = false

    Hartley McGuire

  • Clear locking column on #dup

    This change fixes not to duplicate locking_column like id and timestamps.

    car = Car.create!
    car.touch
    car.lock_version #=> 1
    car.dup.lock_version #=> 0

    Shouichi Kamiya, Seonggi Yang, Ryohei UEDA

  • Invalidate transaction as early as possible

    After rescuing a TransactionRollbackError exception Rails invalidates transactions earlier in the flow allowing the framework to skip issuing the ROLLBACK statement in more cases. Only affects adapters that have savepoint_errors_invalidate_transactions? configured as true, which at this point is only applicable to the mysql2 adapter.

    Nikita Vasilevsky

  • Allow configuring columns list to be used in SQL queries issued by an ActiveRecord::Base object

    It is now possible to configure columns list that will be used to build an SQL query clauses when updating, deleting or reloading an ActiveRecord::Base object

    class Developer < ActiveRecord::Base
      query_constraints :company_id, :id
    end
    developer = Developer.first.update(name: "Bob")

=> UPDATE "developers" SET "name" = 'Bob' WHERE "developers"."company_id" = 1 AND "developers"."id" = 1

```

*Nikita Vasilevsky*
  • Adds validate to foreign keys and check constraints in schema.rb

    Previously, schema.rb would not record if validate: false had been used when adding a foreign key or check constraint, so restoring a database from the schema could result in foreign keys or check constraints being incorrectly validated.

    Tommy Graves

  • Adapter #execute methods now accept an allow_retry option. When set to true, the SQL statement will be retried, up to the database's configured connection_retries value, upon encountering connection-related errors.

    Adrianna Chang

  • Only trigger after_commit :destroy callbacks when a database row is deleted.

    This prevents after_commit :destroy callbacks from being triggered again when destroy is called multiple times on the same record.

    Ben Sheldon

  • Fix ciphertext_for for yet-to-be-encrypted values.

    Previously, ciphertext_for returned the cleartext of values that had not yet been encrypted, such as with an unpersisted record:

    Post.encrypts :body
    
    post = Post.create!(body: "Hello")
    post.ciphertext_for(:body)

=> "{"p":"abc..."

  post.body = "World"
  post.ciphertext_for(:body)

=> "World"

  ```

Now, `ciphertext_for` will always return the ciphertext of encrypted
attributes:

  ```ruby
  Post.encrypts :body

  post = Post.create!(body: "Hello")
  post.ciphertext_for(:body)

=> "{"p":"abc..."

  post.body = "World"
  post.ciphertext_for(:body)

=> "{"p":"xyz..."

  ```

*Jonathan Hefner*
  • Fix a bug where using groups and counts with long table names would return incorrect results.

    Shota Toguchi, Yusaku Ono

  • Fix encryption of column default values.

    Previously, encrypted attributes that used column default values appeared to be encrypted on create, but were not:

    Book.encrypts :name
    
    book = Book.create!
    book.name

=> ""

  book.name_before_type_cast

=> "{"p":"abc..."

  book.reload.name_before_type_cast

=> ""

  ```

Now, attributes with column default values are encrypted:

  ```ruby
  Book.encrypts :name

  book = Book.create!
  book.name

=> ""

  book.name_before_type_cast

=> "{"p":"abc..."

  book.reload.name_before_type_cast

=> "{"p":"abc..."

  ```

*Jonathan Hefner*
  • Deprecate delegation from Base to connection_handler.

    Calling Base.clear_all_connections!, Base.clear_active_connections!, Base.clear_reloadable_connections! and Base.flush_idle_connections! is deprecated. Please call these methods on the connection handler directly. In future Rails versions, the delegation from Base to the connection_handler will be removed.

    Eileen M. Uchitelle

  • Allow ActiveRecord::QueryMethods#reselect to receive hash values, similar to ActiveRecord::QueryMethods#select

    Sampat Badhe

  • Validate options when managing columns and tables in migrations.

    If an invalid option is passed to a migration method like create_table and add_column, an error will be raised instead of the option being silently ignored. Validation of the options will only be applied for new migrations that are created.

    Guo Xiang Tan, George Wambold

  • Update query log tags to use the SQLCommenter format by default. See #​46179

    To opt out of SQLCommenter-formatted query log tags, set config.active_record.query_log_tags_format = :legacy. By default, this is set to :sqlcommenter.

    Modulitos and Iheanyi

  • Allow any ERB in the database.yml when creating rake tasks.

    Any ERB can be used in database.yml even if it accesses environment configurations.

    Deprecates config.active_record.suppress_multiple_database_warning.

    Eike Send

  • Add table to error for duplicate column definitions.

    If a migration defines duplicate columns for a table, the error message shows which table it concerns.

    Petrik de Heus

  • Fix erroneous nil default precision on virtual datetime columns.

    Prior to this change, virtual datetime columns did not have the same default precision as regular datetime columns, resulting in the following being erroneously equivalent:

    t.virtual :name, type: datetime,                 as: "expression"
    t.virtual :name, type: datetime, precision: nil, as: "expression"

    This change fixes the default precision lookup, so virtual and regular datetime column default precisions match.

    Sam Bostock

  • Use connection from #with_raw_connection in #quote_string.

    This ensures that the string quoting is wrapped in the reconnect and retry logic that #with_raw_connection offers.

    Adrianna Chang

  • Add expires_at option to signed_id.

    Shouichi Kamiya

  • Allow applications to set retry deadline for query retries.

    Building on the work done in #​44576 and #​44591, we extend the logic that automatically reconnects database connections to take into account a timeout limit. We won't retry a query if a given amount of time has elapsed since the query was first attempted. This value defaults to nil, meaning that all retryable queries are retried regardless of time elapsed, but this can be changed via the retry_deadline option in the database config.

    Adrianna Chang

  • Fix a case where the query cache can return wrong values. See #​46044

    Aaron Patterson

  • Support MySQL's ssl-mode option for MySQLDatabaseTasks.

    Verifying the identity of the database server requires setting the ssl-mode option to VERIFY_CA or VERIFY_IDENTITY. This option was previously ignored for MySQL database tasks like creating a database and dumping the structure.

    Petrik de Heus

  • Move ActiveRecord::InternalMetadata to an independent object.

    ActiveRecord::InternalMetadata no longer inherits from ActiveRecord::Base and is now an independent object that should be instantiated with a connection. This class is private and should not be used by applications directly. If you want to interact with the schema migrations table, please access it on the connection directly, for example: ActiveRecord::Base.connection.schema_migration.

    Eileen M. Uchitelle

  • Deprecate quoting ActiveSupport::Duration as an integer

    Using ActiveSupport::Duration as an interpolated bind parameter in a SQL string template is deprecated. To avoid this warning, you should explicitly convert the duration to a more specific database type. For example, if you want to use a duration as an integer number of seconds:

    Record.where("duration = ?", 1.hour.to_i)

    If you want to use a duration as an ISO 8601 string:

    Record.where("duration = ?", 1.hour.iso8601)

    Aram Greenman

  • Allow QueryMethods#in_order_of to order by a string column name.

    Post.in_order_of("id", [4,2,3,1]).to_a
    Post.joins(:author).in_order_of("authors.name", ["Bob", "Anna", "John"]).to_a

    Igor Kasyanchuk

  • Move ActiveRecord::SchemaMigration to an independent object.

    ActiveRecord::SchemaMigration no longer inherits from ActiveRecord::Base and is now an independent object that should be instantiated with a connection. This class is private and should not be used by applications directly. If you want to interact with the schema migrations table, please access it on the connection directly, for example: ActiveRecord::Base.connection.schema_migration.

    Eileen M. Uchitelle

  • Deprecate all_connection_pools and make connection_pool_list more explicit.

    Following on #​45924 all_connection_pools is now deprecated. connection_pool_list will either take an explicit role or applications can opt into the new behavior by passing :all.

    Eileen M. Uchitelle

  • Fix connection handler methods to operate on all pools.

    active_connections?, clear_active_connections!, clear_reloadable_connections!, clear_all_connections!, and flush_idle_connections! now operate on all pools by default. Previously they would default to using the current_role or :writing role unless specified.

    Eileen M. Uchitelle

  • Allow ActiveRecord::QueryMethods#select to receive hash values.

    Currently, select might receive only raw sql and symbols to define columns and aliases to select.

    With this change we can provide hash as argument, for example:

    Post.joins(:comments).select(posts: [:id, :title, :created_at], comments: [:id, :body, :author_id])
    #=> "SELECT \"posts\".\"id\", \"posts\".\"title\", \"posts\".\"created_at\", \"comments\".\"id\", \"comments\".\"body\", \"comments\".\"author_id\"

FROM "posts" INNER JOIN "comments" ON "comments"."post_id" = "posts"."id""

Post.joins(:comments).select(posts: { id: :post_id, title: :post_title }, comments: { id: :comment_id, body: :comment_body })
#=> "SELECT posts.id as post_id, posts.title as post_title, comments.id as comment_id, comments.body as comment_body

FROM "posts" INNER JOIN "comments" ON "comments"."post_id" = "posts"."id""

```
*Oleksandr Holubenko*, *Josef Šimánek*, *Jean Boussier*
  • Adapts virtual attributes on ActiveRecord::Persistence#becomes.

    When source and target classes have a different set of attributes adapts attributes such that the extra attributes from target are added.

    class Person < ApplicationRecord
    end
    
    class WebUser < Person
      attribute :is_admin, :boolean
      after_initialize :set_admin
    
      def set_admin
        write_attribute(:is_admin, email =~ /@&#8203;ourcompany\.com$/)
      end
    end
    
    person = Person.find_by(email: "email@ourcompany.com")
    person.respond_to? :is_admin

=> false

person.becomes(WebUser).is_admin?

=> true

```

*Jacopo Beschi*, *Sampson Crowley*
  • Fix ActiveRecord::QueryMethods#in_order_of to include nils, to match the behavior of Enumerable#in_order_of.

    For example, Post.in_order_of(:title, [nil, "foo"]) will now include posts with nil titles, the same as Post.all.to_a.in_order_of(:title, [nil, "foo"]).

    fatkodima

  • Optimize add_timestamps to use a single SQL statement.

    add_timestamps :my_table

    Now results in the following SQL:

    ALTER TABLE "my_table" ADD COLUMN "created_at" datetime(6) NOT NULL, ADD COLUMN "updated_at" datetime(6) NOT NULL

    Iliana Hadzhiatanasova

  • Add drop_enum migration command for PostgreSQL

    This does the inverse of create_enum. Before dropping an enum, ensure you have dropped columns that depend on it.

    Alex Ghiculescu

  • Adds support for if_exists option when removing a check constraint.

    The remove_check_constraint method now accepts an if_exists option. If set to true an error won't be raised if the check constraint doesn't exist.

    Margaret Parsa and Aditya Bhutani

  • find_or_create_by now try to find a second time if it hits a unicity constraint.

    find_or_create_by always has been inherently racy, either creating multiple duplicate records or failing with ActiveRecord::RecordNotUnique depending on whether a proper unicity constraint was set.

    create_or_find_by was introduced for this use case, however it's quite wasteful when the record is expected to exist most of the time, as INSERT require to send more data than SELECT and require more work from the database. Also on some databases it can actually consume a primary key increment which is undesirable.

    So for case where most of the time the record is expected to exist, find_or_create_by can be made race-condition free by re-trying the find if the create failed with ActiveRecord::RecordNotUnique. This assumes that the table has the proper unicity constraints, if not, find_or_create_by will still lead to duplicated records.

    Jean Boussier, Alex Kitchens

  • Introduce a simpler constructor API for ActiveRecord database adapters.

    Previously the adapter had to know how to build a new raw connection to support reconnect, but also expected to be passed an initial already- established connection.

    When manually creating an adapter instance, it will now accept a single config hash, and only establish the real connection on demand.

    Matthew Draper

  • Avoid redundant SELECT 1 connection-validation query during DB pool checkout when possible.

    If the first query run during a request is known to be idempotent, it can be used directly to validate the connection, saving a network round-trip.

    Matthew Draper

  • Automatically reconnect broken database connections when safe, even mid-request.

    When an error occurs while attempting to run a known-idempotent query, and not inside a transaction, it is safe to immediately reconnect to the database server and try again, so this is now the default behavior.

    This new default should always be safe -- to support that, it's consciously conservative about which queries are considered idempotent -- but if necessary it can be disabled by setting the connection_retries connection option to 0.

    Matthew Draper

  • Avoid removing a PostgreSQL extension when there are dependent objects.

    Previously, removing an extension also implicitly removed dependent objects. Now, this will raise an error.

    You can force removing the extension:

    disable_extension :citext, force: :cascade

    Fixes #​29091.

    fatkodima

  • Allow nested functions as safe SQL string

    Michael Siegfried

  • Allow destroy_association_async_job= to be configured with a class string instead of a constant.

    Defers an autoloading dependency between ActiveRecord::Base and ActiveJob::Base and moves the configuration of ActiveRecord::DestroyAssociationAsyncJob from ActiveJob to ActiveRecord.

    Deprecates ActiveRecord::ActiveJobRequiredError and now raises a NameError if the job class is unloadable or an ActiveRecord::ConfigurationError if dependent: :destroy_async is declared on an association but there is no job class configured.

    Ben Sheldon

  • Fix ActiveRecord::Store to serialize as a regular Hash

    Previously it would serialize as an ActiveSupport::HashWithIndifferentAccess which is wasteful and cause problem with YAML safe_load.

    Jean Boussier

  • Add timestamptz as a time zone aware type for PostgreSQL

    This is required for correctly parsing timestamp with time zone values in your database.

    If you don't want this, you can opt out by adding this initializer:

    ActiveRecord::Base.time_zone_aware_types -= [:timestamptz]

    Alex Ghiculescu

  • Add new ActiveRecord::Base.generates_token_for API.

    Currently, signed_id fulfills the role of generating tokens for e.g. resetting a password. However, signed IDs cannot reflect record state, so if a token is intended to be single-use, it must be tracked in a database at least until it expires.

    With generates_token_for, a token can embed data from a record. When using the token to fetch the record, the data from the token and the current data from the record will be compared. If the two do not match, the token will be treated as invalid, the same as if it had expired. For example:

    class User < ActiveRecord::Base
      has_secure_password
    
      generates_token_for :password_reset, expires_in: 15.minutes do

A password's BCrypt salt changes when the password is updated.

By embedding (part of) the salt in a token, the token will

expire when the password is updated.

    BCrypt::Password.new(password_digest).salt[-10..]
  end
end

user = User.first
token = user.generate_token_for(:password_reset)

User.find_by_token_for(:password_reset, token) # => user

user.update!(password: "new password")
User.find_by_token_for(:password_reset, token) # => nil
```

*Jonathan Hefner*
  • Optimize Active Record batching for whole table iterations.

    Previously, in_batches got all the ids and constructed an IN-based query for each batch. When iterating over the whole tables, this approach is not optimal as it loads unneeded ids and IN queries with lots of items are slow.

    Now, whole table iterations use range iteration (id >= x AND id <= y) by default which can make iteration several times faster. E.g., tested on a PostgreSQL table with 10 million records: querying (253s vs 30s), updating (288s vs 124s), deleting (268s vs 83s).

    Only whole table iterations use this style of iteration by default. You can disable this behavior by passing use_ranges: false. If you iterate over the table and the only condition is, e.g., archived_at: nil (and only a tiny fraction of the records are archived), it makes sense to opt in to this approach:

    Project.where(archived_at: nil).in_batches(use_ranges: true) do |relation|

do something

end
```

See #&#8203;45414 for more details.

*fatkodima*
  • .with query method added. Construct common table expressions with ease and get ActiveRecord::Relation back.

    Post.with(posts_with_comments: Post.where("comments_count > ?", 0))

=> ActiveRecord::Relation

WITH posts_with_comments AS (SELECT * FROM posts WHERE (comments_count > 0)) SELECT * FROM posts

```

*Vlado Cingel*
  • Don't establish a new connection if an identical pool exists already.

    Previously, if establish_connection was called on a class that already had an established connection, the existing connection would be removed regardless of whether it was the same config. Now if a pool is found with the same values as the new connection, the existing connection will be returned instead of creating a new one.

    This has a slight change in behavior if application code is depending on a new connection being established regardless of whether it's identical to an existing connection. If the old behavior is desirable, applications should call ActiveRecord::Base#remove_connection before establishing a new one. Calling establish_connection with a different config works the same way as it did previously.

    Eileen M. Uchitelle

  • Update db:prepare task to load schema when an uninitialized database exists, and dump schema after migrations.

    Ben Sheldon

  • Fix supporting timezone awareness for tsrange and tstzrange array columns.

In database migrations

add_column :shops, :open_hours, :tsrange, array: true

In app config

ActiveRecord::Base.time_zone_aware_types += [:tsrange]

In the code times are properly converted to app time zone

Shop.create!(open_hours: [Time.current..8.hour.from_now])
```

*Wojciech Wnętrzak*
  • Introduce strategy pattern for executing migrations.

    By default, migrations will use a strategy object that delegates the method to the connection adapter. Consumers can implement custom strategy objects to change how their migrations run.

    Adrianna Chang

  • Add adapter option disallowing foreign keys

    This adds a new option to be added to database.yml which enables skipping foreign key constraints usage even if the underlying database supports them.

    Usage:

    development:
        <<: *default
        database: storage/development.sqlite3
        foreign_keys: false

    Paulo Barros

  • Add configurable deprecation warning for singular associations

    This adds a deprecation warning when using the plural name of a singular associations in where. It is possible to opt into the new more performant behavior with config.active_record.allow_deprecated_singular_associations_name = false

    Adam Hess

  • Run transactional callbacks on the freshest instance to save a given record within a transaction.

    When multiple Active Record instances change the same record within a transaction, Rails runs after_commit or after_rollback callbacks for only one of them. config.active_record.run_commit_callbacks_on_first_saved_instances_in_transaction was added to specify how Rails chooses which instance receives the callbacks. The framework defaults were changed to use the new logic.

    When config.active_record.run_commit_callbacks_on_first_saved_instances_in_transaction is true, transactional callbacks are run on the first instance to save, even though its instance state may be stale.

    When it is false, which is the new framework default starting with version 7.1, transactional callbacks are run on the instances with the freshest instance state. Those instances are chosen as follows:

    • In general, run transactional callbacks on the last instance to save a given record within the transaction.
    • There are two exceptions:
      • If the record is created within the transaction, then updated by another instance, after_create_commit callbacks will be run on the second instance. This is instead of the after_update_commit callbacks that would naively be run based on that instance’s state.
      • If the record is destroyed within the transaction, then after_destroy_commit callbacks will be fired on the last destroyed instance, even if a stale instance subsequently performed an update (which will have affected 0 rows).

    Cameron Bothner and Mitch Vollebregt

  • Enable strict strings mode for SQLite3Adapter.

    Configures SQLite with a strict strings mode, which disables double-quoted string literals.

    SQLite has some quirks around double-quoted string literals. It first tries to consider double-quoted strings as identifier names, but if they don't exist it then considers them as string literals. Because of this, typos can silently go unnoticed. For example, it is possible to create an index for a non existing column. See SQLite documentation for more details.

    If you don't want this behavior, you can disable it via:

config/application.rb

config.active_record.sqlite3_adapter_strict_strings_by_default = false
```

Fixes #&#8203;27782.

*fatkodima*, *Jean Boussier*
  • Resolve issue where a relation cache_version could be left stale.

    Previously, when reset was called on a relation object it did not reset the cache_versions ivar. This led to a confusing situation where despite having the correct data the relation still reported a stale cache_version.

    Usage:

    developers = Developer.all
    developers.cache_version
    
    Developer.update_all(updated_at: Time.now.utc + 1.second)
    
    developers.cache_version # Stale cache_version
    developers.reset
    developers.cache_version # Returns the current correct cache_version

    Fixes #​45341.

    Austen Madden

  • Add support for exclusion constraints (PostgreSQL-only).

    add_exclusion_constraint :invoices, "daterange(start_date, end_date) WITH &&", using: :gist, name: "invoices_date_overlap"
    remove_exclusion_constraint :invoices, name: "invoices_date_overlap"

    See PostgreSQL's CREATE TABLE ... EXCLUDE ... documentation for more on exclusion constraints.

    Alex Robbin

  • change_column_null raises if a non-boolean argument is provided

    Previously if you provided a non-boolean argument, change_column_null would treat it as truthy and make your column nullable. This could be surprising, so now the input must be either true or false.

    change_column_null :table, :column, true # good
    change_column_null :table, :column, false # good
    change_column_null :table, :column, from: true, to: false # raises (previously this made the column nullable)

    Alex Ghiculescu

  • Enforce limit on table names length.

    Fixes #​45130.

    fatkodima

  • Adjust the minimum MariaDB version for check constraints support.

    Eddie Lebow

  • Fix Hstore deserialize regression.

    edsharp

  • Add validity for PostgreSQL indexes.

    connection.index_exists?(:users, :email, valid: true)
    connection.indexes(:users).select(&:valid?)

    fatkodima

  • Fix eager loading for models without primary keys.

    Anmol Chopra, Matt Lawrence, and Jonathan Hefner

  • Avoid validating a unique field if it has not changed and is backed by a unique index.

    Previously, when saving a record, Active Record will perform an extra query to check for the uniqueness of each attribute having a uniqueness validation, even if that attribute hasn't changed. If the database has the corresponding unique index, then this validation can never fail for persisted records, and we could safely skip it.

    fatkodima

  • Stop setting sql_auto_is_null

    Since version 5.5 the default has been off, we no longer have to manually turn it off.

    Adam Hess

  • Fix touch to raise an error for readonly columns.

    fatkodima

  • Add ability to ignore tables by regexp for SQL schema dumps.

    ActiveRecord::SchemaDumper.ignore_tables = [/^_/]

    fatkodima

  • Avoid queries when performing calculations on contradictory relations.

    Previously calculations would make a query even when passed a contradiction, such as User.where(id: []).count. We no longer perform a query in that scenario.

    This applies to the following calculations: count, sum, average, minimum and maximum

    Luan Vieira, John Hawthorn and Daniel Colson

  • Allow using aliased attributes with insert_all/upsert_all.

    class Book < ApplicationRecord
      alias_attribute :title, :name
    end
    
    Book.insert_all [{ title: "Remote", author_id: 1 }], returning: :title

    fatkodima

  • Support encrypted attributes on columns with default db values.

    This adds support for encrypted attributes defined on columns with default values. It will encrypt those values at creation time. Before, it would raise an error unless config.active_record.encryption.support_unencrypted_data was true.

    Jorge Manrubia and Dima Fatko

  • Allow overriding reading_request? in DatabaseSelector::Resolver

    The default implementation checks if a request is a get? or head?, but you can now change it to anything you like. If the method returns true, Resolver#read gets called meaning the request could be served by the replica database.

    Alex Ghiculescu

  • Remove ActiveRecord.legacy_connection_handling.

    Eileen M. Uchitelle

  • rails db:schema:{dump,load} now checks ENV["SCHEMA_FORMAT"] before config

    Since rails db:structure:{dump,load} was deprecated there wasn't a simple way to dump a schema to both SQL and Ruby formats. You can now do this with an environment variable. For example:

    SCHEMA_FORMAT=sql rake db:schema:dump

    Alex Ghiculescu

  • Fixed MariaDB default function support.

    Defaults would be written wrong in "db/schema.rb" and not work correctly if using db:schema:load. Further more the function name would be added as string content when saving new records.

    kaspernj

  • Add active_record.destroy_association_async_batch_size configuration

    This allows applications to specify the maximum number of records that will be destroyed in a single background job by the dependent: :destroy_async association option. By default, the current behavior will remain the same: when a parent record is destroyed, all dependent records will be destroyed in a single background job. If the number of dependent records is greater than this configuration, the records will be destroyed in multiple background jobs.

    Nick Holden

  • Fix remove_foreign_key with :if_exists option when foreign key actually exists.

    fatkodima

  • Remove --no-comments flag in structure dumps for PostgreSQL

    This broke some apps that used custom schema comments. If you don't want comments in your structure dump, you can use:

    ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = ['--no-comments']

    Alex Ghiculescu

  • Reduce the memory footprint of fixtures accessors.

    Until now fixtures accessors were eagerly defined using define_method. So the memory usage was directly dependent of the number of fixtures and test suites.

    Instead fixtures accessors are now implemented with method_missing, so they incur much less memory and CPU overhead.

    Jean Boussier

  • Fix config.active_record.destroy_association_async_job configuration

    config.active_record.destroy_association_async_job should allow applications to specify the job that will be used to destroy associated records in the background for has_many associations with the dependent: :destroy_async option. Previously, that was ignored, which meant the default ActiveRecord::DestroyAssociationAsyncJob always destroyed records in the background.

    Nick Holden

  • Fix change_column_comment to preserve column's AUTO_INCREMENT in the MySQL adapter

    fatkodima

  • Fix quoting of ActiveSupport::Duration and Rational numbers in the MySQL adapter.

    Kevin McPhillips

  • Allow column name with COLLATE (e.g., title COLLATE "C") as safe SQL string

    Shugo Maeda

  • Permit underscores in the VERSION argument to database rake tasks.

    Eddie Lebow

  • Reversed the order of INSERT statements in structure.sql dumps

    This should decrease the likelihood of merge conflicts. New migrations will now be added at the top of the list.

    For existing apps, there will be a large diff the next time structure.sql is generated.

    Alex Ghiculescu, Matt Larraz

  • Fix PG.connect keyword arguments deprecation warning on ruby 2.7

    Fixes #​44307.

    Nikita Vasilevsky

  • Fix dropping DB connections after serialization failures and deadlocks.

    Prior to 6.1.4, serialization failures and deadlocks caused rollbacks to be issued for both real transactions and savepoints. This breaks MySQL which disallows rollbacks of savepoints following a deadlock.

    6.1.4 removed these rollbacks, for both transactions and savepoints, causing the DB connection to be left in an unknown state and thus discarded.

    These rollbacks are now restored, except for savepoints on MySQL.

    Thomas Morgan

  • Make ActiveRecord::ConnectionPool Fiber-safe

    When ActiveSupport::IsolatedExecutionState.isolation_level is set to :fiber, the connection pool now supports multiple Fibers from the same Thread checking out connections from the pool.

    Alex Matchneer

  • Add update_attribute! to ActiveRecord::Persistence

    Similar to update_attribute, but raises ActiveRecord::RecordNotSaved when a before_* callback throws :abort.

    class Topic < ActiveRecord::Base
      before_save :check_title
    
      def check_title
        throw(:abort) if title == "abort"
      end
    end
    
    topic = Topic.create(title: "Test Title")

#=> #<Topic title: "Test Title">

topic.update_attribute!(:title, "Another Title")

#=> #<Topic title: "Another Title">

topic.update_attribute!(:title, "abort")

raises ActiveRecord::RecordNotSaved

```

*Drew Tempelmeyer*
  • Avoid loading every record in ActiveRecord::Relation#pretty_print

Before

pp Foo.all # Loads the whole table.

After

pp Foo.all # Shows 10 items and an ellipsis.
```

*Ulysse Buonomo*
  • Change QueryMethods#in_order_of to drop records not listed in values.

    in_order_of now filters down to the values provided, to match the behavior of the Enumerable version.

    Kevin Newton

  • Allow named expression indexes to be revertible.

    Previously, the following code would raise an error in a reversible migration executed while rolling back, due to the index name not being used in the index removal.

    add_index(:settings, "(data->'property')", using: :gin, name: :index_settings_data_property)

    Fixes #​43331.

    Oliver Günther

  • Fix incorrect argument in PostgreSQL structure dump tasks.

    Updating the --no-comment argument added in Rails 7 to the correct --no-comments argument.

    Alex Dent

  • Fix migration compatibility to create SQLite references/belongs_to column as integer when migration version is 6.0.

    Reference/belongs_to in migrations with version 6.0 were creating columns as bigint instead of integer for the SQLite Adapter.

    Marcelo Lauxen

  • Fix QueryMethods#in_order_of to handle empty order list.

    Post.in_order_of(:id, []).to_a

    Also more explicitly set the column as secondary order, so that any other value is still ordered.

    Jean Boussier

  • Fix quoting of column aliases generated by calculation methods.

    Since the alias is derived from the table name, we can't assume the result is a valid identifier.

    class Test < ActiveRecord::Base
      self.table_name = '1abc'
    end
    Test.group(:id).count

syntax error at or near "1" (ActiveRecord::StatementInvalid)

LINE 1: SELECT COUNT(*) AS count_all, "1abc"."id" AS 1abc_id FROM "1...

```

*Jean Boussier*
  • Add authenticate_by when using has_secure_password.

    authenticate_by is intended to replace code like the following, which returns early when a user with a matching email is not found:

    User.find_by(email: "...")&.authenticate("...")

    Such code is vulnerable to timing-based enumeration attacks, wherein an attacker can determine if a user account with a given email exists. After confirming that an account exists, the attacker can try passwords associated with that email address from other leaked databases, in case the user re-used a password across multiple sites (a common practice). Additionally, knowing an account email address allows the attacker to attempt a targeted phishing ("spear phishing") attack.

    authenticate_by addresses the vulnerability by taking the same amount of time regardless of whether a user with a matching email is found:

    User.authenticate_by(email: "...", password: "...")

    Jonathan Hefner

Action View

  • Introduce ActionView::TestCase.register_parser

    register_parser :rss, -> rendered { RSS::Parser.parse(rendered) }
    
    test "renders RSS" do
      article = Article.create!(title: "Hello, world")
    
      render formats: :rss, partial: article
    
      assert_equal "Hello, world", rendered.rss.items.last.title
    end

    By default, register parsers for :html and :json.

    Sean Doyle

  • Fix simple_format with blank wrapper_tag option returns plain html tag

    By default simple_format method returns the text wrapped with <p>. But if we explicitly specify the wrapper_tag: nil in the options, it returns the text wrapped with <></> tag.

    Before:

    simple_format("Hello World", {},  { wrapper_tag: nil })

<>Hello World</>

```

After:

```ruby
simple_format("Hello World", {},  { wrapper_tag: nil })

Hello World

`

v7.0.8: 7.0.8

Compare Source

Active Support

  • Fix TimeWithZone still using deprecated #to_s when ENV or config to disable it are set.

    Hartley McGuire

  • Fix CacheStore#write_multi when using a distributed Redis cache with a connection pool.

    Fixes #​48938.

    Jonathan del Strother

Active Model

  • No changes.

Active Record

  • Fix change_column not setting precision: 6 on datetime columns when using 7.0+ Migrations and SQLite.

    Hartley McGuire

  • Fix unscope is not working in specific case

    Before:

    Post.where(id: 1...3).unscope(where: :id).to_sql # "SELECT `posts`.* FROM `posts` WHERE `posts`.`id` >= 1 AND `posts`.`id` < 3"
    

    After:

    Post.where(id: 1...3).unscope(where: :id).to_sql # "SELECT `posts`.* FROM `posts`"

    Fixes #​48094.

    Kazuya Hatanaka

  • Fix associations to a STI model including a class_name parameter

    class Product < ApplicationRecord
      has_many :requests, as: :requestable, class_name: "ProductRequest", dependent: :destroy
    end

STI tables

class Request < ApplicationRecord
  belongs_to :requestable, polymorphic: true

  validate :request_type, presence: true
end

class ProductRequest < Request
  belongs_to :user
end
```

Accessing such association would lead to:

```
table_metadata.rb:22:in `has_column?': undefined method `key?' for nil:NilClass (NoMethodError)
```

*Romain Filinto*
  • Fix change_table setting datetime precision for 6.1 Migrations

    Hartley McGuire

  • Fix change_column setting datetime precision for 6.1 Migrations

    Hartley McGuire

Action View

  • Fix form_for missing the hidden _method input for models with a namespaced route.

    Hartley McGuire

  • Fix render collection: @&#8203;records, cache: true inside jbuilder templates

    The previous fix that shipped in 7.0.7 assumed template fragments are always strings, this isn't true with jbuilder.

    Jean Boussier

Action Pack

  • Fix HostAuthorization potentially displaying the value of the X_FORWARDED_HOST header when the HTTP_HOST header is being blocked.

    Hartley McGuire, Daniel Schlosser

Active Job

  • Fix Active Job log message to correctly report a job failed to enqueue when the adapter raises an ActiveJob::EnqueueError.

    Ben Sheldon

Action Mailer

  • No changes.

Action Cable

  • No changes.

Active Storage

  • No changes.

Action Mailbox

  • No changes.

Action Text

  • No changes.

Railties

  • Omit webdrivers gem dependency from Gemfile template

    Sean Doyle

v7.0.7.2: 7.0.7.2

Compare Source

No changes between this and 7.0.7.2. This release was just to fix file permissions in the previous release.

v7.0.7.1: 7.0.7.1

Compare Source

Active Support

  • Use a temporary file for storing unencrypted files while editing

    [CVE-2023-38037]

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • No changes.

Action Pack

  • No changes.

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.

v7.0.7: 7.0.7

Compare Source

Active Support

  • Fix Cache::NullStore with local caching for repeated reads.

    fatkodima

  • Fix to_s with no arguments not respecting custom :default formats

    Hartley McGuire

  • Fix ActiveSupport::Inflector.humanize(nil) raising NoMethodError: undefined method `end_with?' for nil:NilClass.

    James Robinson

  • Fix Enumerable#sum for Enumerator#lazy.

    fatkodima, Matthew Draper, Jonathan Hefner

  • Improve error message when EventedFileUpdateChecker is used without a compatible version of the Listen gem

    Hartley McGuire

Active Model

  • Error.full_message now strips ":base" from the message.

    zzak

  • Add a load hook for ActiveModel::Model (named active_model) to match the load hook for ActiveRecord::Base and allow for overriding aspects of the ActiveModel::Model class.

Active Record

  • Restores functionality to the missing method when using enums and fixes.

    paulreece

  • Fix StatementCache::Substitute with serialized type.

    ywenc

  • Fix :db_runtime on notification payload when application have multiple databases.

    Eileen M. Uchitelle

  • Correctly dump check constraints for MySQL 8.0.16+.

    Steve Hill

  • Fix ActiveRecord::QueryMethods#in_order_of to include nils, to match the behavior of Enumerable#in_order_of.

    For example, Post.in_order_of(:title, [nil, "foo"]) will now include posts with nil titles, the same as Post.all.to_a.in_order_of(:title, [nil, "foo"]).

    fatkodima

  • Revert "Fix autosave associations with validations added on :base of the associated objects."

    This change intended to remove the :base attribute from the message, but broke many assumptions which key these errors were stored.

    zzak

  • Fix #previously_new_record? to return true for destroyed records.

    Before, if a record was created and then destroyed, #previously_new_record? would return true. Now, any UPDATE or DELETE to a record is considered a change, and will result in #previously_new_record? returning false.

    Adrianna Chang

  • Revert breaking changes to has_one relationship deleting the old record before the new one is validated.

    zzak

  • Fix support for Active Record instances being uses in queries.

    As of 7.0.5, query arguments were deep duped to avoid mutations impacting the query cache, but this had the adverse effect to clearing the primary key when the query argument contained an ActiveRecord::Base instance.

    This broke the noticed gem.

    Jean Boussier

Action View

  • Fix render collection: @&#8203;records, cache: true to cache fragments as bare strings

    Previously it would incorrectly cache them as Action View buffers.

    Jean Boussier

  • Don't double-encode nested field_id and field_name index values

    Pass index: @&#8203;options as a default keyword argument to field_id and field_name view helper methods.

    Sean Doyle

Action Pack

  • No changes.

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

  • Update default scaffold templates to set 303 (See Other) as status code on redirect for the update action for XHR requests other than GET or POST to avoid issues (e.g browsers trying to follow the redirect using the original request method resulting in double PATCH/PUT)

    Guillermo Iguaran

v7.0.6: 7.0.6

Compare Source

Active Support

  • Fix EncryptedConfiguration returning incorrect values for some Hash methods

    Hartley McGuire

  • Fix arguments being destructed Enumerable#many? with block.

    Andrew Novoselac

  • Fix humanize for strings ending with id.

    fatkodima

Active Model

  • No changes.

Active Record

  • Fix autosave associations with validations added on :base of the associated objects.

    fatkodima

  • Fix result with anonymous PostgreSQL columns of different type from json.

    Oleksandr Avoiants

  • Preserve timestamp when setting an ActiveSupport::TimeWithZone value to timestamptz attribute.

    fatkodima

  • Fix where on association with has_one/has_many polymorphic relations.

    Before:

    Treasure.where(price_estimates: PriceEstimate.all)
    #=> SELECT (...) WHERE "treasures"."id" IN (SELECT "price_estimates"."estimate_of_id" FROM "price_estimates")

    Later:

    Treasure.where(price_estimates: PriceEstimate.all)
    #=> SELECT (...) WHERE "treasures"."id" IN (SELECT "price_estimates"."estimate_of_id" FROM "price_estimates" WHERE "price_estimates"."estimate_of_type" = 'Treasure')

    Lázaro Nixon

  • Fix decrementing counter caches on optimistically locked record deletion

    fatkodima

  • Ensure binary-destined values have binary encoding during type cast.

    Matthew Draper

  • Preserve existing column default functions when altering table in SQLite.

    fatkodima

  • Remove table alias added when using where.missing or where.associated.

    fatkodima

  • Fix Enumerable#in_order_of to only flatten first level to preserve nesting.

    Miha Rekar

Action View

  • No changes.

Action Pack

  • No changes.

Active Job

  • Fix error Active Job passed class with permitted?.

    Alex Baldwin

Action Mailer

  • No changes.

Action Cable

  • Fix Action Cable Redis configuration with sentinels.

    Dmitriy Ivliev

Active Storage

  • Fix retrieving rotation value from FFmpeg on version 5.0+.

    In FFmpeg version 5.0+ the rotation value has been removed from tags. Instead the value can be found in side_data_list. Along with this update it's possible to have values of -90, -270 to denote the video has been rotated.

    Haroon Ahmed

Action Mailbox

  • No changes.

Action Text

  • No changes.

Railties

  • Avoid escaping paths when editing credentials.

    Jonathan Hefner

v7.0.5.1

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • No changes.

Action Pack

  • Raise an exception if illegal characters are provide to redirect_to [CVE-2023-28362]

    Zack Deveau

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.

v7.0.5

Compare Source

Active Support

  • Fixes TimeWithZone ArgumentError.

    Niklas Häusele

Active Model

  • No changes.

Active Record

  • Type cast #attribute_changed? :from and :to options.

    Andrew Novoselac

  • Fix index_exists? when column is an array.

    Eileen M. Uchitelle

  • Handle Date objects for PostgreSQL timestamptz columns.

    Alex Ghiculescu

  • Fix collation for changing column to non-string.

    Hartley McGuire

  • Map through subtype in PostgreSQL::OID::Array.

    Jonathan Hefner

  • Store correct environment in internal_metadata when run rails db:prepare.

    fatkodima

  • Make sure ActiveRecord::Relation#sum works with objects that implement #coerce without deprecation.

    Alex Ghiculescu

  • Fix retrieving foreign keys referencing tables named like keywords in PostgreSQL and MySQL.

    fatkodima

  • Support UUIDs in Disable Joins.

    Samuel Cochran

  • Fix Active Record's explain for queries starting with comments.

    fatkodima

  • Fix incorrectly preloading through association records when middle association has been loaded.

    Joshua Young

  • Fix where.missing and where.associated for parent/child associations.

    fatkodima

  • Fix Enumerable#in_order_of to preserve duplicates.

    fatkodima

  • Fix autoincrement on primary key for mysql.

    Eileen M. Uchitelle

  • Restore ability to redefine column in create_table for Rails 5.2 migrations.

    fatkodima

  • Fix schema cache dumping of virtual columns.

    fatkodima

  • Fix Active Record grouped calculations on joined tables on column present in both tables.

    fatkodima

  • Fix mutation detection for serialized attributes backed by binary columns.

    Jean Boussier

  • Fix a bug where using groups and counts with long table names would return incorrect results.

    Shota Toguchi, Yusaku Ono

  • Fix erroneous nil default precision on virtual datetime columns.

    Prior to this change, virtual datetime columns did not have the same default precision as regular datetime columns, resulting in the following being erroneously equivalent:

    t.virtual :name, type: datetime,                 as: "expression"
    t.virtual :name, type: datetime, precision: nil, as: "expression"

    This change fixes the default precision lookup, so virtual and regular datetime column default precisions match.

    Sam Bostock

  • Fix a case where the query cache can return wrong values. See #​46044

    Aaron Patterson

Action View

  • FormBuilder#id finds id set by form_for and form_with.

    Matt Polito

  • Allow all available locales for template lookups.

    Ben Dilley

  • Choices of select can optionally contain html attributes as the last element of the child arrays when using grouped/nested collections

    <%= form.select :foo, [["North America", [["United States","US"],["Canada","CA"]], { disabled: "disabled" }]] %>

=> United States Canada

```

*Chris Gunther*

Action Pack

  • Do not return CSP headers for 304 Not Modified responses.

    Tobias Kraze

  • Fix EtagWithFlash when there is no Flash middleware available.

    fatkodima

  • Fix content-type header with send_stream.

    Elliot Crosby-McCullough

  • Address Selenium :capabilities deprecation warning.

    Ron Shinall

  • Fix cookie domain for domain: all on two letter single level TLD.

    John Hawthorn

  • Don't double log the controller, action, or namespaced_controller when using ActiveRecord::QueryLog

    Previously if you set config.active_record.query_log_tags to an array that included :controller, :namespaced_controller, or :action, that item would get logged twice. This bug has been fixed.

    Alex Ghiculescu

  • Rescue EOFError exception from rack on a multipart request.

    Nikita Vasilevsky

  • Rescue JSON::ParserError in Cookies json deserializer to discards marshal dumps:

    Without this change, if action_dispatch.cookies_serializer is set to :json and the app tries to read a :marshal serialized cookie, it would error out which wouldn't clear the cookie and force app users to manually clear it in their browser.

    (See #​45127 for original bug discussion)

    Nathan Bardoux

Active Job

  • Make delayed job display_name failsafe.

    codez

  • Don't double log the job when using ActiveRecord::QueryLog

    Previously if you set config.active_record.query_log_tags to an array that included :job, the job name would get logged twice. This bug has been fixed.

    Alex Ghiculescu

Action Mailer

  • No changes.

Action Cable

  • Restore Action Cable Redis pub/sub listener on connection failure.

    Vladimir Dementyev

Active Storage

  • No changes.

Action Mailbox

  • No changes.

Action Text

  • Fix ActionText::Attachable#as_json.

    Alexandre Ruban

Railties

  • Add puma app server to Gemfile in order to start test/dummy.

    Donapieppo

  • Rails console now disables IRB's autocompletion feature in production by default.

    Setting IRB_USE_AUTOCOMPLETE=true can override this default.

    Stan Lo

  • Send 303 See Other status code back for the destroy action on newly generated scaffold controllers.

    Tony Drake

v7.0.4.3

Compare Source

Active Support

  • Implement SafeBuffer#bytesplice

    [CVE-2023-28120]

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • Ignore certain data-* attributes in rails-ujs when element is contenteditable

    [CVE-2023-23913]

Action Pack

  • No changes.

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.

v7.0.4.2

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • No changes.

Action Pack

  • Fix domain: :all for two letter TLD

    This fixes a compatibility issue introduced in our previous security release when using domain: :all with a two letter but single level top level domain domain (like .ca, rather than .co.uk).

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.

v7.0.4.1

Compare Source

This is a security release. More information is available in our security announcements forum: https://discuss.rubyonrails.org/c/security-announcements/9

Active Support

  • Avoid regex backtracking in Inflector.underscore

    [CVE-2023-22796]

Active Model

  • No changes.

Active Record

  • Make sanitize_as_sql_comment more strict

    Though this method was likely never meant to take user input, it was attempting sanitization. That sanitization could be bypassed with carefully crafted input.

    This commit makes the sanitization more robust by replacing any occurrances of "/" or "/" with "/ " or " /". It also performs a first pass to remove one surrounding comment to avoid compatibility issues for users relying on the existing removal.

    This also clarifies in the documentation of annotate that it should not be provided user input.

    [CVE-2023-22794]

  • Added integer width check to PostgreSQL::Quoting

    Given a value outside the range for a 64bit signed integer type PostgreSQL will treat the column type as numeric. Comparing integer values against numeric values can result in a slow sequential scan.

    This behavior is configurable via ActiveRecord::Base.raise_int_wider_than_64bit which defaults to true.

    [CVE-2022-44566]

Action View

  • No changes.

Action Pack

  • Fix sec issue with _url_host_allowed?

    Disallow certain strings from _url_host_allowed? to avoid a redirect to malicious sites.

    [CVE-2023-22797]

  • Avoid regex backtracking on If-None-Match header

    [CVE-2023-22795]

  • Use string#split instead of regex for domain parts

    [CVE-2023-22792]

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.

v7.0.4

Compare Source

Active Support

  • Redis cache store is now compatible with redis-rb 5.0.

    Jean Boussier

  • Fix NoMethodError on custom ActiveSupport::Deprecation behavior.

    ActiveSupport::Deprecation.behavior= was supposed to accept any object that responds to call, but in fact its internal implementation assumed that this object could respond to arity, so it was restricted to only Proc objects.

    This change removes this arity restriction of custom behaviors.

    Ryo Nakamura

Active Model

  • Handle name clashes in attribute methods code generation cache.

    When two distinct attribute methods would generate similar names, the first implementation would be incorrectly re-used.

    class A
      attribute_method_suffix "_changed?"
      define_attribute_methods :x
    end
    
    class B
      attribute_method_suffix "?"
      define_attribute_methods :x_changed
    end

    Jean Boussier

Active Record

  • Symbol is allowed by default for YAML columns

    Étienne Barrié

  • Fix ActiveRecord::Store to serialize as a regular Hash

    Previously it would serialize as an ActiveSupport::HashWithIndifferentAccess which is wasteful and cause problem with YAML safe_load.

    Jean Boussier

  • Add timestamptz as a time zone aware type for PostgreSQL

    This is required for correctly parsing timestamp with time zone values in your database.

    If you don't want this, you can opt out by adding this initializer:

    ActiveRecord::Base.time_zone_aware_types -= [:timestamptz]

    Alex Ghiculescu

  • Fix supporting timezone awareness for tsrange and tstzrange array columns.

In database migrations

add_column :shops, :open_hours, :tsrange, array: true

In app config

ActiveRecord::Base.time_zone_aware_types += [:tsrange]

In the code times are properly converted to app time zone

Shop.create!(open_hours: [Time.current..8.hour.from_now])
```

*Wojciech Wnętrzak*
  • Resolve issue where a relation cache_version could be left stale.

    Previously, when reset was called on a relation object it did not reset the cache_versions ivar. This led to a confusing situation where despite having the correct data the relation still reported a stale cache_version.

    Usage:

    developers = Developer.all
    developers.cache_version
    
    Developer.update_all(updated_at: Time.now.utc + 1.second)
    
    developers.cache_version # Stale cache_version
    developers.reset
    developers.cache_version # Returns the current correct cache_version

    Fixes #​45341.

    Austen Madden

  • Fix load_async when called on an association proxy.

    Calling load_async directly an association would schedule a query but never use it.

    comments = post.comments.load_async # schedule a query
    comments.to_a # perform an entirely new sync query

    Now it does use the async query, however note that it doesn't cause the association to be loaded.

    Jean Boussier

  • Fix eager loading for models without primary keys.

    Anmol Chopra, Matt Lawrence, and Jonathan Hefner

  • rails db:schema:{dump,load} now checks ENV["SCHEMA_FORMAT"] before config

    Since rails db:structure:{dump,load} was deprecated there wasn't a simple way to dump a schema to both SQL and Ruby formats. You can now do this with an environment variable. For example:

    SCHEMA_FORMAT=sql rake db:schema:dump

    Alex Ghiculescu

  • Fix Hstore deserialize regression.

    edsharp

Action View

  • Guard against ActionView::Helpers::FormTagHelper#field_name calls with nil object_name arguments. For example:

    <%= fields do |f| %>
      <%= f.field_name :body %>
    <% end %>

    Sean Doyle

  • Strings returned from strip_tags are correctly tagged html_safe?

    Because these strings contain no HTML elements and the basic entities are escaped, they are safe to be included as-is as PCDATA in HTML content. Tagging them as html-safe avoids double-escaping entities when being concatenated to a SafeBuffer during rendering.

    Fixes rails/rails-html-sanitizer#124

    Mike Dalessio

Action Pack

  • Prevent ActionDispatch::ServerTiming from overwriting existing values in Server-Timing.

    Previously, if another middleware down the chain set Server-Timing header, it would overwritten by ActionDispatch::ServerTiming.

    Jakub Malinowski

Active Job

  • Update ActiveJob::QueueAdapters::QueAdapter to remove deprecation warning.

    Remove a deprecation warning introduced in que 1.2 to prepare for changes in que 2.0 necessary for Ruby 3 compatibility.

    Damir Zekic and Adis Hasovic

Action Mailer

  • No changes.

Action Cable

  • The Redis adapter is now compatible with redis-rb 5.0

    Compatibility with redis-rb 3.x was dropped.

    Jean Boussier

  • The Action Cable server is now mounted with anchor: true.

    This means that routes that also start with /cable will no longer clash with Action Cable.

    Alex Ghiculescu

Active Storage

  • Fixes proxy downloads of files over 5MiB

    Previously, trying to view and/or download files larger than 5mb stored in services like S3 via proxy mode could return corrupted files at around 5.2mb or cause random halts in the download. Now, ActiveStorage::Blobs::ProxyController correctly handles streaming these larger files from the service to the client without any issues.

    Fixes #​44679

    Felipe Raul

Action Mailbox

  • No changes.

Action Text

  • No changes.

Railties

  • config.allow_concurrency = false now use a Monitor instead of a Mutex

    This allows to enable config.active_support.executor_around_test_case even when config.allow_concurrency is disabled.

    Jean Boussier

  • Skip Active Storage and Action Mailer if Active Job is skipped.

    Étienne Barrié

  • Correctly check if frameworks are disabled when running app:update.

    Étienne Barrié and Paulo Barros

  • Fixed config.active_support.cache_format_version never being applied.

    Rails 7.0 shipped with a new serializer for Rails.cache, but the associated config wasn't working properly. Note that even after this fix, it can only be applied from the application.rb file.

    Alex Ghiculescu

v7.0.3.1: 7.0.3.1

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • Change ActiveRecord::Coders::YAMLColumn default to safe_load

    This adds two new configuration options The configuration options are as follows:

    • config.active_storage.use_yaml_unsafe_load

    When set to true, this configuration option tells Rails to use the old "unsafe" YAML loading strategy, maintaining the existing behavior but leaving the possible escalation vulnerability in place. Setting this option to true is not recommended, but can aid in upgrading.

    • config.active_record.yaml_column_permitted_classes

    The "safe YAML" loading method does not allow all classes to be deserialized by default. This option allows you to specify classes deemed "safe" in your application. For example, if your application uses Symbol and Time in serialized data, you can add Symbol and Time to the allowed list as follows:

    config.active_record.yaml_column_permitted_classes = [Symbol, Date, Time]

    [CVE-2022-32224]

Action View

  • No changes.

Action Pack

  • No changes.

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.

v7.0.3: 7.0.3

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • Some internal housekeeping on reloads could break custom respond_to? methods in class objects that referenced reloadable constants. See #​44125 for details.

    Xavier Noria

  • Fixed MariaDB default function support.

    Defaults would be written wrong in "db/schema.rb" and not work correctly if using db:schema:load. Further more the function name would be added as string content when saving new records.

    kaspernj

  • Fix remove_foreign_key with :if_exists option when foreign key actually exists.

    fatkodima

  • Remove --no-comments flag in structure dumps for PostgreSQL

    This broke some apps that used custom schema comments. If you don't want comments in your structure dump, you can use:

    ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = ['--no-comments']

    Alex Ghiculescu

  • Use the model name as a prefix when filtering encrypted attributes from logs.

    For example, when encrypting Person#name it will add person.name as a filter parameter, instead of just name. This prevents unintended filtering of parameters with a matching name in other models.

    Jorge Manrubia

  • Fix quoting of ActiveSupport::Duration and Rational numbers in the MySQL adapter.

    Kevin McPhillips

  • Fix change_column_comment to preserve column's AUTO_INCREMENT in the MySQL adapter

    fatkodima

Action View

  • Ensure models passed to form_for attempt to call to_model.

    Sean Doyle

Action Pack

  • Allow relative redirects when raise_on_open_redirects is enabled.

    Tom Hughes

  • Fix authenticate_with_http_basic to allow for missing password.

    Before Rails 7.0 it was possible to handle basic authentication with only a username.

    authenticate_with_http_basic do |token, _|
      ApiClient.authenticate(token)
    end

    This ability is restored.

    Jean Boussier

  • Fix content_security_policy returning invalid directives.

    Directives such as self, unsafe-eval and few others were not single quoted when the directive was the result of calling a lambda returning an array.

    content_security_policy do |policy|
      policy.frame_ancestors lambda { [:self, "https://example.com"] }
    end

    With this fix the policy generated from above will now be valid.

    Edouard Chin

  • Fix skip_forgery_protection to run without raising an error if forgery protection has not been enabled / verify_authenticity_token is not a defined callback.

    This fix prevents the Rails 7.0 Welcome Page (/) from raising an ArgumentError if default_protect_from_forgery is false.

    Brad Trick

  • Fix ActionController::Live to copy the IsolatedExecutionState in the ephemeral thread.

    Since its inception ActionController::Live has been copying thread local variables to keep things such as CurrentAttributes set from middlewares working in the controller action.

    With the introduction of IsolatedExecutionState in 7.0, some of that global state was lost in ActionController::Live controllers.

    Jean Boussier

  • Fix setting trailing_slash: true in route definition.

    get '/test' => "test#index", as: :test, trailing_slash: true
    
    test_path() # => "/test/"

    Jean Boussier

Active Job

  • Add missing bigdecimal require in ActiveJob::Arguments

    Could cause uninitialized constant ActiveJob::Arguments::BigDecimal (NameError) when loading Active Job in isolation.

    Jean Boussier

Action Mailer

  • No changes.

Action Cable

  • No changes.

Active Storage

  • Don't stream responses in redirect mode

    Previously, both redirect mode and proxy mode streamed their responses which caused a new thread to be created, and could end up leaking connections in the connection pool. But since redirect mode doesn't actually send any data, it doesn't need to be streamed.

    Luke Lau

Action Mailbox

  • No changes.

Action Text

  • No changes.

Railties

  • If reloading and eager loading are both enabled, after a reload Rails eager loads again the application code.

    Xavier Noria

  • Use controller_class_path in Rails::Generators::NamedBase#route_url

    The route_url method now returns the correct path when generating a namespaced controller with a top-level model using --model-name.

    Previously, when running this command:

    bin/rails generate scaffold_controller Admin/Post --model-name Post

    the comments above the controller action would look like:

GET /posts

def index
  @&#8203;posts = Post.all
end
```

afterwards, they now look like this:

``` ruby

GET /admin/posts

def index
  @&#8203;posts = Post.all
end
```

Fixes #&#8203;44662.

*Andrew White*

v7.0.2.4

Compare Source

Active Support

  • Fix and add protections for XSS in ActionView::Helpers and ERB::Util.

    Add the method ERB::Util.xml_name_escape to escape dangerous characters in names of tags and names of attributes, following the specification of XML.

    Álvaro Martín Fraguas

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • Fix and add protections for XSS in ActionView::Helpers and ERB::Util.

    Escape dangerous characters in names of tags and names of attributes in the tag helpers, following the XML specification. Rename the option :escape_attributes to :escape, to simplify by applying the option to the whole tag.

    Álvaro Martín Fraguas

Action Pack

  • Allow Content Security Policy DSL to generate for API responses.

    Tim Wade

Active Job

  • No changes.

Action Mailer

  • No changes.

Action Cable

  • No changes.

Active Storage

  • No changes.

Railties

  • No changes.

v7.0.2.3: 7.0.2.3

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • No changes.

Action Pack

  • No changes.

Active Job

  • No changes.

Action Mailer

  • No changes.

Action Cable

  • No changes.

Active Storage

  • Added image transformation validation via configurable allow-list.

    Variant now offers a configurable allow-list for transformation methods in addition to a configurable deny-list for arguments.

    [CVE-2022-21831]

Action Mailbox

  • No changes.

Action Text

  • No changes.

Railties

  • No changes.

v7.0.2.2: 7.0.2.2

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • No changes.

Action Pack

  • Fix Reloader method signature to work with the new Executor signature

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.

v7.0.2.1: 7.0.2.1

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • No changes.

Action Pack

  • Under certain circumstances, the middleware isn't informed that the response body has been fully closed which result in request state not being fully reset before the next request

    [CVE-2022-23633]

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.

v7.0.2: 7.0.2

Compare Source

Active Support

  • Fix ActiveSupport::EncryptedConfiguration to be compatible with Psych 4

    Stephen Sugden

  • Improve File.atomic_write error handling.

    Daniel Pepper

Active Model

  • Use different cache namespace for proxy calls

    Models can currently have different attribute bodies for the same method names, leading to conflicts. Adding a new namespace :active_model_proxy fixes the issue.

    Chris Salzberg

Active Record

  • Fix PG.connect keyword arguments deprecation warning on ruby 2.7.

    Nikita Vasilevsky

  • Fix the ability to exclude encryption params from being autofiltered.

    Mark Gangl

  • Dump the precision for datetime columns following the new defaults.

    Rafael Mendonça França

  • Make sure encrypted attributes are not being filtered twice.

    Nikita Vasilevsky

  • Dump the database schema containing the current Rails version.

    Since https://github.com/rails/rails/pull/42297, Rails now generate datetime columns with a default precision of 6. This means that users upgrading to Rails 7.0 from 6.1, when loading the database schema, would get the new precision value, which would not match the production schema.

    To avoid this the schema dumper will generate the new format which will include the Rails version and will look like this:

    ActiveRecord::Schema[7.0].define

    When upgrading from Rails 6.1 to Rails 7.0, you can run the rails app:update task that will set the current schema version to 6.1.

    Rafael Mendonça França

  • Fix parsing expression for PostgreSQL generated column.

    fatkodima

  • Fix Mysql2::Error: Commands out of sync; you can't run this command now when bulk-inserting fixtures that exceed max_allowed_packet configuration.

    Nikita Vasilevsky

  • Fix error when saving an association with a relation named record.

    Dorian Marié

  • Fix MySQL::SchemaDumper behavior about datetime precision value.

    y0t4

  • Improve associated with no reflection error.

    Nikolai

  • Fix PG.connect keyword arguments deprecation warning on ruby 2.7.

    Fixes #​44307.

    Nikita Vasilevsky

  • Fix passing options to check_constraint from change_table.

    Frederick Cheung

Action View

  • Ensure preload_link_tag preloads JavaScript modules correctly.

    Máximo Mussini

  • Fix stylesheet_link_tag and similar helpers are being used to work in objects with a response method.

    dark-panda

Action Pack

  • No changes.

Active Job

  • No changes.

Action Mailer

  • No changes.

Action Cable

  • No changes.

Active Storage

  • Revert the ability to pass service_name param to DirectUploadsController which was introduced in 7.0.0.

    That change caused a lot of problems to upgrade Rails applications so we decided to remove it while in work in a more backwards compatible implementation.

    Gannon McGibbon

  • Allow applications to opt out of precompiling Active Storage JavaScript assets.

    jlestavel

Action Mailbox

  • No changes.

Action Text

  • No changes.

Railties

  • No changes.

v7.0.1: 7.0.1

Compare Source

Active Support

Active Model

  • No changes.

Active Record

  • Change QueryMethods#in_order_of to drop records not listed in values.

    in_order_of now filters down to the values provided, to match the behavior of the Enumerable version.

    Kevin Newton

  • Allow named expression indexes to be revertible.

    Previously, the following code would raise an error in a reversible migration executed while rolling back, due to the index name not being used in the index removal.

    add_index(:settings, "(data->'property')", using: :gin, name: :index_settings_data_property)

    Fixes #​43331.

    Oliver Günther

  • Better error messages when association name is invalid in the argument of ActiveRecord::QueryMethods::WhereChain#missing.

    ykpythemind

  • Fix ordered migrations for single db in multi db environment.

    Himanshu

  • Extract on update CURRENT_TIMESTAMP for mysql2 adapter.

    Kazuhiro Masuda

  • Fix incorrect argument in PostgreSQL structure dump tasks.

    Updating the --no-comment argument added in Rails 7 to the correct --no-comments argument.

    Alex Dent

  • Fix schema dumping column default SQL values for sqlite3.

    fatkodima

  • Correctly parse complex check constraint expressions for PostgreSQL.

    fatkodima

  • Fix timestamptz attributes on PostgreSQL handle blank inputs.

    Alex Ghiculescu

  • Fix migration compatibility to create SQLite references/belongs_to column as integer when migration version is 6.0.

    Reference/belongs_to in migrations with version 6.0 were creating columns as bigint instead of integer for the SQLite Adapter.

    Marcelo Lauxen

  • Fix joining through a polymorphic association.

    Alexandre Ruban

  • Fix QueryMethods#in_order_of to handle empty order list.

    Post.in_order_of(:id, []).to_a

    Also more explicitly set the column as secondary order, so that any other value is still ordered.

    Jean Boussier

  • Fix rails dbconsole for 3-tier config.

    Eileen M. Uchitelle

  • Fix quoting of column aliases generated by calculation methods.

    Since the alias is derived from the table name, we can't assume the result is a valid identifier.

    class Test < ActiveRecord::Base
      self.table_name = '1abc'
    end
    Test.group(:id).count

syntax error at or near "1" (ActiveRecord::StatementInvalid)

LINE 1: SELECT COUNT(*) AS count_all, "1abc"."id" AS 1abc_id FROM "1...

```

*Jean Boussier*

Action View

  • Fix button_to to work with a hash parameter as URL.

    MingyuanQin

  • Fix link_to with a model passed as an argument twice.

    Alex Ghiculescu

Action Pack

  • Fix ActionController::Parameters methods to keep the original logger context when creating a new copy of the original object.

    Yutaka Kamei

Active Job

  • Allow testing discard_on/retry_on ActiveJob::DeserializationError

    Previously in perform_enqueued_jobs, deserialize_arguments_if_needed was called before calling perform_now. When a record no longer exists and is serialized using GlobalID this led to raising an ActiveJob::DeserializationError before reaching perform_now call. This behaviour makes difficult testing the job discard_on/retry_on logic.

    Now deserialize_arguments_if_needed call is postponed to when perform_now is called.

    Example:

    class UpdateUserJob < ActiveJob::Base
      discard_on ActiveJob::DeserializationError
    
      def perform(user)

...

  end
end

In the test

User.destroy_all
assert_nothing_raised do
  perform_enqueued_jobs only: UpdateUserJob
end
```

*Jacopo Beschi*

Action Mailer

  • Keep configuration of smtp_settings consistent between 6.1 and 7.0.

    André Luis Leal Cardoso Junior

Action Cable

  • No changes.

Active Storage

  • No changes.

Action Mailbox

  • No changes.

Action Text

  • No changes.

Railties

  • Prevent duplicate entries in plugin Gemfile.

    Jonathan Hefner

  • Fix asset pipeline errors for plugin dummy apps.

    Jonathan Hefner

  • Fix generated route revocation.

    Jonathan Hefner

  • Addresses an issue in which Sidekiq jobs could not reload certain namespaces.

    See fxn/zeitwerk#198 for details.

    Xavier Noria

  • Fix plugin generator to a plugin that pass all the tests.

    Rafael Mendonça França

v7.0.0: 7.0.0

Compare Source

Action Cable

  • The Action Cable client now ensures successful channel subscriptions:

    • The client maintains a set of pending subscriptions until either the server confirms the subscription or the channel is torn down.
    • Rectifies the race condition where an unsubscribe is rapidly followed by a subscribe (on the same channel identifier) and the requests are handled out of order by the ActionCable server, thereby ignoring the subscribe command.

    Daniel Spinosa

  • Compile ESM package that can be used directly in the browser as actioncable.esm.js.

    DHH

  • Move action_cable.js to actioncable.js to match naming convention used for other Rails frameworks, and use JS console to communicate the deprecation.

    DHH

  • Stop transpiling the UMD package generated as actioncable.js and drop the IE11 testing that relied on that.

    DHH

  • Truncate broadcast logging messages.

    J Smith

  • OpenSSL constants are now used for Digest computations.

    Dirkjan Bussink

  • The Action Cable client now includes safeguards to prevent a "thundering herd" of client reconnects after server connectivity loss:

    • The client will wait a random amount between 1x and 3x of the stale threshold after the server's last ping before making the first reconnection attempt.
    • Subsequent reconnection attempts now use exponential backoff instead of logarithmic backoff. To allow the delay between reconnection attempts to increase slowly at first, the default exponentiation base is < 2.
    • Random jitter is applied to each delay between reconnection attempts.

    Jonathan Hefner

Action Mailbox

  • Removed deprecated environment variable MAILGUN_INGRESS_API_KEY.

    Rafael Mendonça França

  • Removed deprecated Rails.application.credentials.action_mailbox.mailgun_api_key.

    Rafael Mendonça França

  • Add attachments to the list of permitted parameters for inbound emails conductor.

    When using the conductor to test inbound emails with attachments, this prevents an unpermitted parameter warning in default configurations, and prevents errors for applications that set:

    config.action_controller.action_on_unpermitted_parameters = :raise

    David Jones, Dana Henke

  • Add ability to configure ActiveStorage service for storing email raw source.

config/storage.yml

incoming_emails:
  service: Disk
  root: /secure/dir/for/emails/only
```

```ruby
config.action_mailbox.storage_service = :incoming_emails
```

*Yurii Rashkovskii*
  • Add ability to incinerate an inbound message through the conductor interface.

    Santiago Bartesaghi

  • OpenSSL constants are now used for Digest computations.

    Dirkjan Bussink

Action Mailer

  • Remove deprecated ActionMailer::DeliveryJob and ActionMailer::Parameterized::DeliveryJob in favor of ActionMailer::MailDeliveryJob.

    Rafael Mendonça França

  • email_address_with_name returns just the address if name is blank.

    Thomas Hutterer

  • Configures a default of 5 for both open_timeout and read_timeout for SMTP Settings.

    André Luis Leal Cardoso Junior

Action Pack

  • Deprecate Rails.application.config.action_controller.urlsafe_csrf_tokens. This config is now always enabled.

    Étienne Barrié

  • Instance variables set in requests in a ActionController::TestCase are now cleared before the next request

    This means if you make multiple requests in the same test, instance variables set in the first request will not persist into the second one. (It's not recommended to make multiple requests in the same test.)

    Alex Ghiculescu

  • Rails.application.executor hooks can now be called around every request in a ActionController::TestCase

    This helps to better simulate request or job local state being reset between requests and prevent state leaking from one request to another.

    To enable this, set config.active_support.executor_around_test_case = true (this is the default in Rails 7).

    Alex Ghiculescu

  • Consider onion services secure for cookies.

    Justin Tracey

  • Remove deprecated Rails.config.action_view.raise_on_missing_translations.

    Rafael Mendonça França

  • Remove deprecated support to passing a path to fixture_file_upload relative to fixture_path.

    Rafael Mendonça França

  • Remove deprecated ActionDispatch::SystemTestCase#host!.

    Rafael Mendonça França

  • Remove deprecated Rails.config.action_dispatch.hosts_response_app.

    Rafael Mendonça França

  • Remove deprecated ActionDispatch::Response.return_only_media_type_on_content_type.

    Rafael Mendonça França

  • Raise ActionController::Redirecting::UnsafeRedirectError for unsafe redirect_to redirects.

    This allows rescue_from to be used to add a default fallback route:

    rescue_from ActionController::Redirecting::UnsafeRedirectError do
      redirect_to root_url
    end

    Kasper Timm Hansen, Chris Oliver

  • Add url_from to verify a redirect location is internal.

    Takes the open redirect protection from redirect_to so users can wrap a param, and fall back to an alternate redirect URL when the param provided one is unsafe.

    def create
      redirect_to url_from(params[:redirect_url]) || root_url
    end

    dmcge, Kasper Timm Hansen

  • Allow Capybara driver name overrides in SystemTestCase::driven_by

    Allow users to prevent conflicts among drivers that use the same driver type (selenium, poltergeist, webkit, rack test).

    Fixes #​42502

    Chris LaRose

  • Allow multiline to be passed in routes when using wildcard segments.

    Previously routes with newlines weren't detected when using wildcard segments, returning a No route matches error. After this change, routes with newlines are detected on wildcard segments. Example

      draw do
        get "/wildcard/*wildcard_segment", to: SimpleApp.new("foo#index"), as: :wildcard
      end

After the change, the path matches.

  assert_equal "/wildcard/a%0Anewline", url_helpers.wildcard_path(wildcard_segment: "a\nnewline")
```

Fixes #&#8203;39103

*Ignacio Chiazzo*
  • Treat html suffix in controller translation.

    Rui Onodera, Gavin Miller

  • Allow permitting numeric params.

    Previously it was impossible to permit different fields on numeric parameters. After this change you can specify different fields for each numbered parameter. For example params like,

    book: {
            authors_attributes: {
              '0': { name: "William Shakespeare", age_of_death: "52" },
              '1': { name: "Unattributed Assistant" },
              '2': "Not a hash",
              'new_record': { name: "Some name" }
            }
          }

    Before you could permit name on each author with, permit book: { authors_attributes: [ :name ] }

    After this change you can permit different keys on each numbered element, permit book: { authors_attributes: { '1': [ :name ], '0': [ :name, :age_of_death ] } }

    Fixes #​41625

    Adam Hess

  • Update HostAuthorization middleware to render debug info only when config.consider_all_requests_local is set to true.

    Also, blocked host info is always logged with level error.

    Fixes #​42813

    Nikita Vyrko

  • Add Server-Timing middleware

    Server-Timing specification defines how the server can communicate to browsers performance metrics about the request it is responding to.

    The ServerTiming middleware is enabled by default on development environment by default using the config.server_timing setting and set the relevant duration metrics in the Server-Timing header

    The full specification for Server-Timing header can be found in: https://www.w3.org/TR/server-timing/#dfn-server-timing-header-field

    Sebastian Sogamoso, Guillermo Iguaran

  • Use a static error message when raising ActionDispatch::Http::Parameters::ParseError to avoid inadvertently logging the HTTP request body at the fatal level when it contains malformed JSON.

    Fixes #​41145

    Aaron Lahey

  • Add Middleware#delete! to delete middleware or raise if not found.

    Middleware#delete! works just like Middleware#delete but will raise an error if the middleware isn't found.

    Alex Ghiculescu, Petrik de Heus, Junichi Sato

  • Raise error on unpermitted open redirects.

    Add allow_other_host options to redirect_to. Opt in to this behaviour with ActionController::Base.raise_on_open_redirects = true.

    Gannon McGibbon

  • Deprecate poltergeist and webkit (capybara-webkit) driver registration for system testing (they will be removed in Rails 7.1). Add cuprite instead.

    Poltergeist and capybara-webkit are already not maintained. These usage in Rails are removed for avoiding confusing users.

    Cuprite is a good alternative to Poltergeist. Some guide descriptions are replaced from Poltergeist to Cuprite.

    Yusuke Iwaki

  • Exclude additional flash types from ActionController::Base.action_methods.

    Ensures that additional flash types defined on ActionController::Base subclasses are not listed as actions on that controller.

    class MyController < ApplicationController
      add_flash_types :hype
    end
    
    MyController.action_methods.include?('hype') # => false

    Gavin Morrice

  • OpenSSL constants are now used for Digest computations.

    Dirkjan Bussink

  • Remove IE6-7-8 file download related hack/fix from ActionController::DataStreaming module.

    Due to the age of those versions of IE this fix is no longer relevant, more importantly it creates an edge-case for unexpected Cache-Control headers.

    Tadas Sasnauskas

  • Configuration setting to skip logging an uncaught exception backtrace when the exception is present in rescued_responses.

    It may be too noisy to get all backtraces logged for applications that manage uncaught exceptions via rescued_responses and exceptions_app. config.action_dispatch.log_rescued_responses (defaults to true) can be set to false in this case, so that only exceptions not found in rescued_responses will be logged.

    Alexander Azarov, Mike Dalessio

  • Ignore file fixtures on db:fixtures:load.

    Kevin Sjöberg

  • Fix ActionController::Live controller test deadlocks by removing the body buffer size limit for tests.

    Dylan Thacker-Smith

  • New ActionController::ConditionalGet#no_store method to set HTTP cache control no-store directive.

    Tadas Sasnauskas

  • Drop support for the SERVER_ADDR header.

    Following up https://github.com/rack/rack/pull/1573 and https://github.com/rails/rails/pull/42349.

    Ricardo Díaz

  • Set session options when initializing a basic session.

    Gannon McGibbon

  • Add cache_control: {} option to fresh_when and stale?.

    Works as a shortcut to set response.cache_control with the above methods.

    Jacopo Beschi

  • Writing into a disabled session will now raise an error.

    Previously when no session store was set, writing into the session would silently fail.

    Jean Boussier

  • Add support for 'require-trusted-types-for' and 'trusted-types' headers.

    Fixes #​42034.

    lfalcao

  • Remove inline styles and address basic accessibility issues on rescue templates.

    Jacob Herrington

  • Add support for 'private, no-store' Cache-Control headers.

    Previously, 'no-store' was exclusive; no other directives could be specified.

    Alex Smith

  • Expand payload of unpermitted_parameters.action_controller instrumentation to allow subscribers to know which controller action received unpermitted parameters.

    bbuchalter

  • Add ActionController::Live#send_stream that makes it more convenient to send generated streams:

    send_stream(filename: "subscribers.csv") do |stream|
      stream.writeln "email_address,updated_at"
    
      @&#8203;subscribers.find_each do |subscriber|
        stream.writeln [ subscriber.email_address, subscriber.updated_at ].join(",")
      end
    end

    DHH

  • Add ActionController::Live::Buffer#writeln to write a line to the stream with a newline included.

    DHH

  • ActionDispatch::Request#content_type now returned Content-Type header as it is.

    Previously, ActionDispatch::Request#content_type returned value does NOT contain charset part. This behavior changed to returned Content-Type header containing charset part as it is.

    If you want just MIME type, please use ActionDispatch::Request#media_type instead.

    Before:

    request = ActionDispatch::Request.new("CONTENT_TYPE" => "text/csv; header=present; charset=utf-16", "REQUEST_METHOD" => "GET")
    request.content_type #=> "text/csv"

    After:

    request = ActionDispatch::Request.new("Content-Type" => "text/csv; header=present; charset=utf-16", "REQUEST_METHOD" => "GET")
    request.content_type #=> "text/csv; header=present; charset=utf-16"
    request.media_type   #=> "text/csv"

    Rafael Mendonça França

  • Change ActionDispatch::Request#media_type to return nil when the request don't have a Content-Type header.

    Rafael Mendonça França

  • Fix error in ActionController::LogSubscriber that would happen when throwing inside a controller action.

    Janko Marohnić

  • Allow anything with #to_str (like Addressable::URI) as a redirect_to location.

    ojab

  • Change the request method to a GET when passing failed requests down to config.exceptions_app.

    Alex Robbin

  • Deprecate the ability to assign a single value to config.action_dispatch.trusted_proxies as RemoteIp middleware behaves inconsistently depending on whether this is configured with a single value or an enumerable.

    Fixes #​40772.

    Christian Sutter

  • Add redirect_back_or_to(fallback_location, **) as a more aesthetically pleasing version of redirect_back fallback_location:, **. The old method name is retained without explicit deprecation.

    DHH

Action Text

  • Fix an issue with how nested lists were displayed when converting to plain text

    Matt Swanson

  • Allow passing in a custom direct_upload_url or blob_url_template to rich_text_area_tag.

    Lucas Mansur

  • Make the Action Text + Trix JavaScript and CSS available through the asset pipeline.

    DHH

  • OpenSSL constants are now used for Digest computations.

    Dirkjan Bussink

  • Add support for passing form: option to rich_text_area_tag and rich_text_area helpers to specify the <input type="hidden" form="..."> value.

    Sean Doyle

  • Add config.action_text.attachment_tag_name, to specify the HTML tag that contains attachments.

    Mark VanLandingham

  • Expose how we render the HTML surrounding rich text content as an extensible layouts/action_view/contents/_content.html.erb template to encourage user-land customizations, while retaining private API control over how the rich text itself is rendered by action_text/contents/_content.html.erb partial.

    Sean Doyle

  • Add with_all_rich_text method to eager load all rich text associations on a model at once.

    Matt Swanson, DHH

Action View

  • Support include_hidden: option in calls to ActionView::Helper::FormBuilder#file_field with multiple: true to support submitting an empty collection of files.

    form.file_field :attachments, multiple: true

=>

     <input type="file" multiple="multiple" id="post_attachments" name="post[attachments][]">

form.file_field :attachments, multiple: true, include_hidden: false

=>

```

*Sean Doyle*
  • Fix number_with_precision(raise: true) always raising even on valid numbers.

    Pedro Moreira

  • Support fields model: [@&#8203;nested, @&#8203;model] the same way as form_with model: [@&#8203;nested, @&#8203;model].

    Sean Doyle

  • Infer HTTP verb [method] from a model or Array with model as the first argument to button_to when combined with a block:

    button_to(Workshop.find(1)){ "Update" }
    #=> <form method="post" action="/workshops/1" class="button_to">
    #=>   <input type="hidden" name="_method" value="patch" autocomplete="off" />
    #=>   <button type="submit">Update</button>
    #=> </form>
    
    button_to([ Workshop.find(1), Session.find(1) ]) { "Update" }
    #=> <form method="post" action="/workshops/1/sessions/1" class="button_to">
    #=>   <input type="hidden" name="_method" value="patch" autocomplete="off" />
    #=>   <button type="submit">Update</button>
    #=> </form>

    Sean Doyle

  • Support passing a Symbol as the first argument to FormBuilder#button:

    form.button(:draft, value: true)

=> Create post

form.button(:draft, value: true) do
  content_tag(:strong, "Save as draft")
end

=>

Save as draft

```

*Sean Doyle*
  • Introduce the field_name view helper, along with the FormBuilder#field_name counterpart:

    form_for @&#8203;post do |f|
      f.field_tag :tag, name: f.field_name(:tag, multiple: true)

=>

end
```

*Sean Doyle*
  • Execute the ActionView::Base.field_error_proc within the context of the ActionView::Base instance:

    config.action_view.field_error_proc = proc { |html| content_tag(:div, html, class: "field_with_errors") }

    Sean Doyle

  • Add support for button_to ..., authenticity_token: false

    button_to "Create", Post.new, authenticity_token: false

=>

Create
button_to "Create", Post.new, authenticity_token: true

=>

Create
button_to "Create", Post.new, authenticity_token: "secret"

=>

Create
```

*Sean Doyle*
  • Support rendering <form> elements without [action] attributes by:

    • form_with url: false or form_with ..., html: { action: false }
    • form_for ..., url: false or form_for ..., html: { action: false }
    • form_tag false or form_tag ..., action: false
    • button_to "...", false or button_to(false) { ... }

    Sean Doyle

  • Add :day_format option to date_select

    date_select("article", "written_on", day_format: ->(day) { day.ordinalize })

generates day options like 1st\n2nd...

*Shunichi Ikegami*
  • Allow link_to helper to infer link name from Model#to_s when it is used with a single argument:

    link_to @&#8203;profile
    #=> <a href="/profiles/1">Eileen</a>

    This assumes the model class implements a to_s method like this:

    class Profile < ApplicationRecord

...

      def to_s
        name
      end
    end

Previously you had to supply a second argument even if the `Profile`
model implemented a `#to_s` method that called the `name` method.

    link_to @&#8203;profile, @&#8203;profile.name
    #=> <a href="/profiles/1">Eileen</a>

*Olivier Lacan*
  • Support svg unpaired tags for tag helper.

    tag.svg { tag.use('href' => "#cool-icon") }

=>

*Oleksii Vasyliev*
  • Improves the performance of ActionView::Helpers::NumberHelper formatters by avoiding the use of exceptions as flow control.

    Mike Dalessio

  • preload_link_tag properly inserts as attributes for files with image MIME types, such as JPG or SVG.

    Nate Berkopec

  • Add weekday_options_for_select and weekday_select helper methods. Also adds weekday_select to FormBuilder.

    Drew Bragg, Dana Kashubeck, Kasper Timm Hansen

  • Add caching? helper that returns whether the current code path is being cached and uncacheable! to denote helper methods that can't participate in fragment caching.

    Ben Toews, John Hawthorn, Kasper Timm Hansen, Joel Hawksley

  • Add include_seconds option for time_field.

    <%= form.time_field :foo, include_seconds: false %>

=>

Default includes seconds:

    <%= form.time_field :foo %>

=>

This allows you to take advantage of [different rendering options](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/time#time_value_format) in some browsers.

*Alex Ghiculescu*
  • Improve error messages when template file does not exist at absolute filepath.

    Ted Whang

  • Add :country_code option to sms_to for consistency with phone_to.

    Jonathan Hefner

  • OpenSSL constants are now used for Digest computations.

    Dirkjan Bussink

  • The translate helper now passes default values that aren't translation keys through I18n.translate for interpolation.

    Jonathan Hefner

  • Adds option extname to stylesheet_link_tag to skip default .css extension appended to the stylesheet path.

    Before:

    stylesheet_link_tag "style.less"

```

After:

```ruby
stylesheet_link_tag "style.less", extname: false, skip_pipeline: true, rel: "stylesheet/less"

```

*Abhay Nikam*
  • Deprecate render locals to be assigned to instance variables.

    Petrik de Heus

  • Remove legacy default media=screen from stylesheet_link_tag.

    André Luis Leal Cardoso Junior

  • Change ActionView::Helpers::FormBuilder#button to transform formmethod attributes into _method="$VERB" Form Data to enable varied same-form actions:

    <%= form_with model: post, method: :put do %>
      <%= form.button "Update" %>
      <%= form.button "Delete", formmethod: :delete %>
    <% end %>
    <%# => <form action="posts/1">
        =>   <input type="hidden" name="_method" value="put">
        =>   <button type="submit">Update</button>
        =>   <button type="submit" formmethod="post" name="_method" value="delete">Delete</button>
        => </form>
    %>

    Sean Doyle

  • Change ActionView::Helpers::UrlHelper#button_to to always render a <button> element, regardless of whether or not the content is passed as the first argument or as a block.

    <%= button_to "Delete", post_path(@&#8203;post), method: :delete %>

=>

Delete
    <%= button_to post_path(@&#8203;post), method: :delete do %>
      Delete
    <% end %>

=>

Delete
*Sean Doyle*, *Dusan Orlovic*
  • Add config.action_view.preload_links_header to allow disabling of the Link header being added by default when using stylesheet_link_tag and javascript_include_tag.

    Andrew White

  • The translate helper now resolves default values when a nil key is specified, instead of always returning nil.

    Jonathan Hefner

  • Add config.action_view.image_loading to configure the default value of the image_tag :loading option.

    By setting config.action_view.image_loading = "lazy", an application can opt in to lazy loading images sitewide, without changing view code.

    Jonathan Hefner

  • ActionView::Helpers::FormBuilder#id returns the value of the <form> element's id attribute. With a method argument, returns the id attribute for a form field with that name.

    <%= form_for @&#8203;post do |f| %>
      <%# ... %>
    
      <% content_for :sticky_footer do %>
        <%= form.button(form: f.id) %>
      <% end %>
    <% end %>

    Sean Doyle

  • ActionView::Helpers::FormBuilder#field_id returns the value generated by the FormBuilder for the given attribute name.

    <%= form_for @&#8203;post do |f| %>
      <%= f.label :title %>
      <%= f.text_field :title, aria: { describedby: f.field_id(:title, :error) } %>
      <%= tag.span("is blank", id: f.field_id(:title, :error) %>
    <% end %>

    Sean Doyle

  • Add tag.attributes to transform a Hash into HTML Attributes, ready to be interpolated into ERB.

    <input <%= tag.attributes(type: :text, aria: { label: "Search" }) %> >

=>

*Sean Doyle*

Active Job

  • Remove deprecated :return_false_on_aborted_enqueue option.

    Rafael Mendonça França

  • Deprecated Rails.config.active_job.skip_after_callbacks_if_terminated.

    Rafael Mendonça França

  • Removed deprecated behavior that was not halting after_enqueue/after_perform callbacks when a previous callback was halted with throw :abort.

    Rafael Mendonça França

  • Raise an SerializationError in Serializer::ModuleSerializer if the module name is not present.

    Veerpal Brar

  • Allow a job to retry indefinitely

    The attempts parameter of the retry_on method now accepts the symbol reference :unlimited in addition to a specific number of retry attempts to allow a developer to specify that a job should retry forever until it succeeds.

    class MyJob < ActiveJob::Base
      retry_on(AlwaysRetryException, attempts: :unlimited)

the actual job code

    end

*Daniel Morton*
  • Added possibility to check on :priority in test helper methods assert_enqueued_with and assert_performed_with.

    Wojciech Wnętrzak

  • OpenSSL constants are now used for Digest computations.

    Dirkjan Bussink

  • Add a Serializer for the Range class.

    This should allow things like MyJob.perform_later(range: 1..100).

  • Communicate enqueue failures to callers of perform_later.

    perform_later can now optionally take a block which will execute after the adapter attempts to enqueue the job. The block will receive the job instance as an argument even if the enqueue was not successful. Additionally, ActiveJob adapters now have the ability to raise an ActiveJob::EnqueueError which will be caught and stored in the job instance so code attempting to enqueue jobs can inspect any raised EnqueueError using the block.

    MyJob.perform_later do |job|
      unless job.successfully_enqueued?
        if job.enqueue_error&.message == "Redis was unavailable"

invoke some code that will retry the job after a delay

        end
      end
    end

*Daniel Morton*
  • Don't log rescuable exceptions defined with rescue_from.

    Hu Hailin

  • Allow rescue_from to rescue all exceptions.

    Adrianna Chang, Étienne Barrié

Active Model

  • Remove support to Marshal load Rails 5.x ActiveModel::AttributeSet format.

    Rafael Mendonça França

  • Remove support to Marshal and YAML load Rails 5.x error format.

    Rafael Mendonça França

  • Remove deprecated support to use []= in ActiveModel::Errors#messages.

    Rafael Mendonça França

  • Remove deprecated support to delete errors from ActiveModel::Errors#messages.

    Rafael Mendonça França

  • Remove deprecated support to clear errors from ActiveModel::Errors#messages.

    Rafael Mendonça França

  • Remove deprecated support concat errors to ActiveModel::Errors#messages.

    Rafael Mendonça França

  • Remove deprecated ActiveModel::Errors#to_xml.

    Rafael Mendonça França

  • Remove deprecated ActiveModel::Errors#keys.

    Rafael Mendonça França

  • Remove deprecated ActiveModel::Errors#values.

    Rafael Mendonça França

  • Remove deprecated ActiveModel::Errors#slice!.

    Rafael Mendonça França

  • Remove deprecated ActiveModel::Errors#to_h.

    Rafael Mendonça França

  • Remove deprecated enumeration of ActiveModel::Errors instances as a Hash.

    Rafael Mendonça França

  • Clear secure password cache if password is set to nil

    Before:

    user.password = 'something' user.password = nil

    user.password # => 'something'

    Now:

    user.password = 'something' user.password = nil

    user.password # => nil

    Markus Doits

  • Introduce ActiveModel::API.

    Make ActiveModel::API the minimum API to talk with Action Pack and Action View. This will allow adding more functionality to ActiveModel::Model.

    Petrik de Heus, Nathaniel Watts

  • Fix dirty check for Float::NaN and BigDecimal::NaN.

    Float::NaN and BigDecimal::NaN in Ruby are special values and can't be compared with ==.

    Marcelo Lauxen

  • Fix to_json for ActiveModel::Dirty object.

    Exclude mutations_from_database attribute from json as it lead to recursion.

    Anil Maurya

  • Add ActiveModel::AttributeSet#values_for_database.

    Returns attributes with values for assignment to the database.

    Chris Salzberg

  • Fix delegation in ActiveModel::Type::Registry#lookup and ActiveModel::Type.lookup.

    Passing a last positional argument {} would be incorrectly considered as keyword argument.

    Benoit Daloze

  • Cache and re-use generated attribute methods.

    Generated methods with identical implementations will now share their instruction sequences leading to reduced memory retention, and slightly faster load time.

    Jean Boussier

  • Add in: range parameter to numericality validator.

    Michal Papis

  • Add locale argument to ActiveModel::Name#initialize to be used to generate the singular, plural, route_key and singular_route_key values.

    Lukas Pokorny

  • Make ActiveModel::Errors#inspect slimmer for readability

    lulalala

Active Record

  • Better handle SQL queries with invalid encoding.

    Post.create(name: "broken \xC8 UTF-8")

    Would cause all adapters to fail in a non controlled way in the code responsible to detect write queries.

    The query is now properly passed to the database connection, which might or might not be able to handle it, but will either succeed or failed in a more correct way.

    Jean Boussier

  • Move database and shard selection config options to a generator.

    Rather than generating the config options in production.rb when applications are created, applications can now run a generator to create an initializer and uncomment / update options as needed. All multi-db configuration can be implemented in this initializer.

    Eileen M. Uchitelle

  • Remove deprecated ActiveRecord::DatabaseConfigurations::DatabaseConfig#spec_name.

    Rafael Mendonça França

  • Remove deprecated ActiveRecord::Connection#in_clause_length.

    Rafael Mendonça França

  • Remove deprecated ActiveRecord::Connection#allowed_index_name_length.

    Rafael Mendonça França

  • Remove deprecated ActiveRecord::Base#remove_connection.

    Rafael Mendonça França

  • Load STI Models in fixtures

    Data from Fixtures now loads based on the specific class for models with Single Table Inheritance. This affects enums defined in subclasses, previously the value of these fields was not parsed and remained nil

    Andres Howard

  • #authenticate returns false when the password is blank instead of raising an error.

    Muhammad Muhammad Ibrahim

  • Fix ActiveRecord::QueryMethods#in_order_of behavior for integer enums.

    ActiveRecord::QueryMethods#in_order_of didn't work as expected for enums stored as integers in the database when passing an array of strings or symbols as the order argument. This unexpected behavior occurred because the string or symbol values were not casted to match the integers in the database.

    The following example now works as expected:

    class Book < ApplicationRecord
      enum status: [:proposed, :written, :published]
    end
    
    Book.in_order_of(:status, %w[written published proposed])

    Alexandre Ruban

  • Ignore persisted in-memory records when merging target lists.

    Kevin Sjöberg

  • Add a new option :update_only to upsert_all to configure the list of columns to update in case of conflict.

    Before, you could only customize the update SQL sentence via :on_duplicate. There is now a new option :update_only that lets you provide a list of columns to update in case of conflict:

    Commodity.upsert_all(
      [
        { id: 2, name: "Copper", price: 4.84 },
        { id: 4, name: "Gold", price: 1380.87 },
        { id: 6, name: "Aluminium", price: 0.35 }
      ],
      update_only: [:price] # Only prices will be updated
    )

    Jorge Manrubia

  • Remove deprecated ActiveRecord::Result#map! and ActiveRecord::Result#collect!.

    Rafael Mendonça França

  • Remove deprecated ActiveRecord::Base.configurations.to_h.

    Rafael Mendonça França

  • Remove deprecated ActiveRecord::Base.configurations.default_hash.

    Rafael Mendonça França

  • Remove deprecated ActiveRecord::Base.arel_attribute.

    Rafael Mendonça França

  • Remove deprecated ActiveRecord::Base.connection_config.

    Rafael Mendonça França

  • Filter attributes in SQL logs

    Previously, SQL queries in logs containing ActiveRecord::Base.filter_attributes were not filtered.

    Now, the filter attributes will be masked [FILTERED] in the logs when prepared_statement is enabled.

Before:

  Foo Load (0.2ms)  SELECT "foos".* FROM "foos" WHERE "foos"."passw" = ? LIMIT ?  [["passw", "hello"], ["LIMIT", 1]]

After:

  Foo Load (0.5ms)  SELECT "foos".* FROM "foos" WHERE "foos"."passw" = ? LIMIT ?  [["passw", "[FILTERED]"], ["LIMIT", 1]]
```

*Aishwarya Subramanian*
  • Remove deprecated Tasks::DatabaseTasks.spec.

    Rafael Mendonça França

  • Remove deprecated Tasks::DatabaseTasks.current_config.

    Rafael Mendonça França

  • Deprecate Tasks::DatabaseTasks.schema_file_type.

    Rafael Mendonça França

  • Remove deprecated Tasks::DatabaseTasks.dump_filename.

    Rafael Mendonça França

  • Remove deprecated Tasks::DatabaseTasks.schema_file.

    Rafael Mendonça França

  • Remove deprecated environment and name arguments from Tasks::DatabaseTasks.schema_up_to_date?.

    Rafael Mendonça França

  • Merging conditions on the same column no longer maintain both conditions, and will be consistently replaced by the latter condition.

Rails 6.1 (IN clause is replaced by merger side equality condition)

Author.where(id: [david.id, mary.id]).merge(Author.where(id: bob)) # => [bob]

Rails 6.1 (both conflict conditions exists, deprecated)

Author.where(id: david.id..mary.id).merge(Author.where(id: bob)) # => []

Rails 6.1 with rewhere to migrate to Rails 7.0's behavior

Author.where(id: david.id..mary.id).merge(Author.where(id: bob), rewhere: true) # => [bob]

Rails 7.0 (same behavior with IN clause, mergee side condition is consistently replaced)

Author.where(id: [david.id, mary.id]).merge(Author.where(id: bob)) # => [bob]
Author.where(id: david.id..mary.id).merge(Author.where(id: bob)) # => [bob]

*Rafael Mendonça França*
  • Remove deprecated support to Model.reorder(nil).first to search using non-deterministic order.

    Rafael Mendonça França

  • Remove deprecated rake tasks:

    • db:schema:load_if_ruby
    • db:structure:dump
    • db:structure:load
    • db:structure:load_if_sql
    • db:structure:dump:#{name}
    • db:structure:load:#{name}
    • db:test:load_structure
    • db:test:load_structure:#{name}

    Rafael Mendonça França

  • Remove deprecated DatabaseConfig#config method.

    Rafael Mendonça França

  • Rollback transactions when the block returns earlier than expected.

    Before this change, when a transaction block returned early, the transaction would be committed.

    The problem is that timeouts triggered inside the transaction block was also making the incomplete transaction to be committed, so in order to avoid this mistake, the transaction block is rolled back.

    Rafael Mendonça França

  • Add middleware for automatic shard swapping.

    Provides a basic middleware to perform automatic shard swapping. Applications will provide a resolver which will determine for an individual request which shard should be used. Example:

    config.active_record.shard_resolver = ->(request) {
      subdomain = request.subdomain
      tenant = Tenant.find_by_subdomain!(subdomain)
      tenant.shard
    }

    See guides for more details.

    Eileen M. Uchitelle, John Crepezzi

  • Remove deprecated support to pass a column to type_cast.

    Rafael Mendonça França

  • Remove deprecated support to type cast to database values ActiveRecord::Base objects.

    Rafael Mendonça França

  • Remove deprecated support to quote ActiveRecord::Base objects.

    Rafael Mendonça França

  • Remove deprecacated support to resolve connection using "primary" as connection specification name.

    Rafael Mendonça França

  • Remove deprecation warning when using :interval column is used in PostgreSQL database.

    Now, interval columns will return ActiveSupport::Duration objects instead of strings.

    To keep the old behavior, you can add this line to your model:

    attribute :column, :string

    Rafael Mendonça França

  • Remove deprecated support to YAML load ActiveRecord::Base instance in the Rails 4.2 and 4.1 formats.

    Rafael Mendonça França

  • Remove deprecated option :spec_name in the configs_for method.

    Rafael Mendonça França

  • Remove deprecated ActiveRecord::Base.allow_unsafe_raw_sql.

    Rafael Mendonça França

  • Fix regression bug that caused ignoring additional conditions for preloading has_many-through relations.

    Fixes #​43132

    Alexander Pauly

  • Fix has_many inversing recursion on models with recursive associations.

    Gannon McGibbon

  • Add accepts_nested_attributes_for support for delegated_type

    class Entry < ApplicationRecord
      delegated_type :entryable, types: %w[ Message Comment ]
      accepts_nested_attributes_for :entryable
    end
    
    entry = Entry.create(entryable_type: 'Message', entryable_attributes: { content: 'Hello world' })

=> #Entry:0x00

id: 1

entryable_id: 1,

entryable_type: 'Message'

...>

entry.entryable

=> #Message:0x01

id: 1

content: 'Hello world'

...>

```

Previously it would raise an error:

```ruby
Entry.create(entryable_type: 'Message', entryable_attributes: { content: 'Hello world' })

ArgumentError: Cannot build association `entryable'. Are you trying to build a polymorphic one-to-one association?

```

*Sjors Baltus*
  • Use subquery for DELETE with GROUP_BY and HAVING clauses.

    Prior to this change, deletes with GROUP_BY and HAVING were returning an error.

    After this change, GROUP_BY and HAVING are valid clauses in DELETE queries, generating the following query:

    DELETE FROM "posts" WHERE "posts"."id" IN (
        SELECT "posts"."id" FROM "posts" INNER JOIN "comments" ON "comments"."post_id" = "posts"."id" GROUP BY "posts"."id" HAVING (count(comments.id) >= 2))
    )  [["flagged", "t"]]

    Ignacio Chiazzo Cardarello

  • Use subquery for UPDATE with GROUP_BY and HAVING clauses.

    Prior to this change, updates with GROUP_BY and HAVING were being ignored, generating a SQL like this:

    UPDATE "posts" SET "flagged" = ? WHERE "posts"."id" IN (
        SELECT "posts"."id" FROM "posts" INNER JOIN "comments" ON "comments"."post_id" = "posts"."id"
    )  [["flagged", "t"]]

    After this change, GROUP_BY and HAVING clauses are used as a subquery in updates, like this:

    UPDATE "posts" SET "flagged" = ? WHERE "posts"."id" IN (
        SELECT "posts"."id" FROM "posts" INNER JOIN "comments" ON "comments"."post_id" = "posts"."id"
        GROUP BY posts.id HAVING (count(comments.id) >= 2)
    )  [["flagged", "t"]]

    Ignacio Chiazzo Cardarello

  • Add support for setting the filename of the schema or structure dump in the database config.

    Applications may now set their the filename or path of the schema / structure dump file in their database configuration.

    production:
      primary:
        database: my_db
        schema_dump: my_schema_dump_filename.rb
      animals:
        database: animals_db
        schema_dump: false

    The filename set in schema_dump will be used by the application. If set to false the schema will not be dumped. The database tasks are responsible for adding the database directory to the filename. If a full path is provided, the Rails tasks will use that instead of ActiveRecord::DatabaseTasks.db_dir.

    Eileen M. Uchitelle, Ryan Kerr

  • Add ActiveRecord::Base.prohibit_shard_swapping to prevent attempts to change the shard within a block.

    John Crepezzi, Eileen M. Uchitelle

  • Filter unchanged attributes with default function from insert query when partial_inserts is disabled.

    Akshay Birajdar, Jacopo Beschi

  • Add support for FILTER clause (SQL:2003) to Arel.

    Currently supported by PostgreSQL 9.4+ and SQLite 3.30+.

    Andrey Novikov

  • Automatically set timestamps on record creation during bulk insert/upsert

    Prior to this change, only updates during an upsert operation (e.g. upsert_all) would touch timestamps (updated_{at,on}). Now, record creations also touch timestamp columns ({created,updated}_{at,on}).

    This behaviour is controlled by the <model>.record_timestamps config, matching the behaviour of create, update, etc. It can also be overridden by using the record_timestamps: keyword argument.

    Note that this means upsert_all on models with record_timestamps = false will no longer touch updated_{at,on} automatically.

    Sam Bostock

  • Don't require role when passing shard to connected_to.

    connected_to can now be called with a shard only. Note that role is still inherited if connected_to calls are nested.

    Eileen M. Uchitelle

  • Add option to lazily load the schema cache on the connection.

    Previously, the only way to load the schema cache in Active Record was through the Railtie on boot. This option provides the ability to load the schema cache on the connection after it's been established. Loading the cache lazily on the connection can be beneficial for Rails applications that use multiple databases because it will load the cache at the time the connection is established. Currently Railties doesn't have access to the connections before boot.

    To use the cache, set config.active_record.lazily_load_schema_cache = true in your application configuration. In addition a schema_cache_path should be set in your database configuration if you don't want to use the default "db/schema_cache.yml" path.

    Eileen M. Uchitelle

  • Allow automatic inverse_of detection for associations with scopes.

    Automatic inverse_of detection now works for associations with scopes. For example, the comments association here now automatically detects inverse_of: :post, so we don't need to pass that option:

    class Post < ActiveRecord::Base
      has_many :comments, -> { visible }
    end
    
    class Comment < ActiveRecord::Base
      belongs_to :post
    end

    Note that the automatic detection still won't work if the inverse association has a scope. In this example a scope on the post association would still prevent Rails from finding the inverse for the comments association.

    This will be the default for new apps in Rails 7. To opt in:

    config.active_record.automatic_scope_inversing = true

    Daniel Colson, Chris Bloom

  • Accept optional transaction args to ActiveRecord::Locking::Pessimistic#with_lock

    #with_lock now accepts transaction options like requires_new:, isolation:, and joinable:

    John Mileham

  • Adds support for deferrable foreign key constraints in PostgreSQL.

    By default, foreign key constraints in PostgreSQL are checked after each statement. This works for most use cases, but becomes a major limitation when creating related records before the parent record is inserted into the database. One example of this is looking up / creating a person via one or more unique alias.

    Person.transaction do
      alias = Alias
        .create_with(user_id: SecureRandom.uuid)
        .create_or_find_by(name: "DHH")
    
      person = Person
        .create_with(name: "David Heinemeier Hansson")
        .create_or_find_by(id: alias.user_id)
    end

    Using the default behavior, the transaction would fail when executing the first INSERT statement.

    By passing the :deferrable option to the add_foreign_key statement in migrations, it's possible to defer this check.

    add_foreign_key :aliases, :person, deferrable: true

    Passing deferrable: true doesn't change the default behavior, but allows manually deferring the check using SET CONSTRAINTS ALL DEFERRED within a transaction. This will cause the foreign keys to be checked after the transaction.

    It's also possible to adjust the default behavior from an immediate check (after the statement), to a deferred check (after the transaction):

    add_foreign_key :aliases, :person, deferrable: :deferred

    Benedikt Deicke

  • Allow configuring Postgres password through the socket URL.

    For example:

    ActiveRecord::DatabaseConfigurations::UrlConfig.new(
      :production, :production, 'postgres:///?user=user&password=secret&dbname=app', {}
    ).configuration_hash

    will now return,

    { :user=>"user", :password=>"secret", :dbname=>"app", :adapter=>"postgresql" }

    Abeid Ahmed

  • PostgreSQL: support custom enum types

    In migrations, use create_enum to add a new enum type, and t.enum to add a column.

    def up
      create_enum :mood, ["happy", "sad"]
    
      change_table :cats do |t|
        t.enum :current_mood, enum_type: "mood", default: "happy", null: false
      end
    end

    Enums will be presented correctly in schema.rb. Note that this is only supported by the PostgreSQL adapter.

    Alex Ghiculescu

  • Avoid COMMENT statements in PostgreSQL structure dumps

    COMMENT statements are now omitted from the output of db:structure:dump when using PostgreSQL >= 11. This allows loading the dump without a pgsql superuser account.

    Fixes #​36816, #​43107.

    Janosch Müller

  • Add support for generated columns in PostgreSQL adapter

    Generated columns are supported since version 12.0 of PostgreSQL. This adds support of those to the PostgreSQL adapter.

    create_table :users do |t|
      t.string :name
      t.virtual :name_upcased, type: :string, as: 'upper(name)', stored: true
    end

    Michał Begejowicz

  • Remove warning when overwriting existing scopes

    Removes the following unnecessary warning message that appeared when overwriting existing scopes

    Creating scope :my_scope_name. Overwriting existing method "MyClass.my_scope_name" when overwriting existing scopes

    Weston Ganger

  • Use full precision for updated_at in insert_all/upsert_all

    CURRENT_TIMESTAMP provides differing precision depending on the database, and not all databases support explicitly specifying additional precision.

    Instead, we delegate to the new connection.high_precision_current_timestamp for the SQL to produce a high precision timestamp on the current database.

    Fixes #​42992

    Sam Bostock

  • Add ssl support for postgresql database tasks

    Add PGSSLMODE, PGSSLCERT, PGSSLKEY and PGSSLROOTCERT to pg_env from database config when running postgresql database tasks.

config/database.yml

production:
  sslmode: verify-full
  sslcert: client.crt
  sslkey: client.key
  sslrootcert: ca.crt
```

Environment variables

```
PGSSLMODE=verify-full
PGSSLCERT=client.crt
PGSSLKEY=client.key
PGSSLROOTCERT=ca.crt
```

Fixes #&#8203;42994

*Michael Bayucot*
  • Avoid scoping update callbacks in ActiveRecord::Relation#update!.

    Making it consistent with how scoping is applied only to the query in ActiveRecord::Relation#update and not also to the callbacks from the update itself.

    Dylan Thacker-Smith

  • Fix 2 cases that inferred polymorphic class from the association's foreign_type using String#constantize instead of the model's polymorphic_class_for.

    When updating a polymorphic association, the old foreign_type was not inferred correctly when:

    1. touching the previously associated record
    2. updating the previously associated record's counter_cache

    Jimmy Bourassa

  • Add config option for ignoring tables when dumping the schema cache.

    Applications can now be configured to ignore certain tables when dumping the schema cache.

    The configuration option can table an array of tables:

    config.active_record.schema_cache_ignored_tables = ["ignored_table", "another_ignored_table"]

    Or a regex:

    config.active_record.schema_cache_ignored_tables = [/^_/]

    Eileen M. Uchitelle

  • Make schema cache methods return consistent results.

    Previously the schema cache methods primary_keys, columns, columns_hash, and indexes would behave differently than one another when a table didn't exist and differently across database adapters. This change unifies the behavior so each method behaves the same regardless of adapter.

    The behavior now is:

    columns: (unchanged) raises a db error if the table does not exist. columns_hash: (unchanged) raises a db error if the table does not exist. primary_keys: (unchanged) returns nil if the table does not exist. indexes: (changed for mysql2) returns [] if the table does not exist.

    Eileen M. Uchitelle

  • Reestablish connection to previous database after after running db:schema:load:name

    After running db:schema:load:name the previous connection is restored.

    Jacopo Beschi

  • Add database config option database_tasks

    If you would like to connect to an external database without any database management tasks such as schema management, migrations, seeds, etc. you can set the per database config option database_tasks: false

config/database.yml

production:
  primary:
    database: my_database
    adapter: mysql2
  animals:
    database: my_animals_database
    adapter: mysql2
    database_tasks: false
```

*Weston Ganger*
  • Fix ActiveRecord::InternalMetadata to not be broken by config.active_record.record_timestamps = false

    Since the model always create the timestamp columns, it has to set them, otherwise it breaks various DB management tasks.

    Fixes #​42983

  • Add ActiveRecord::QueryLogs.

    Configurable tags can be automatically added to all SQL queries generated by Active Record.

config/application.rb

module MyApp
  class Application < Rails::Application
    config.active_record.query_log_tags_enabled = true
  end
end
```

By default the application, controller and action details are added to the query tags:

```ruby
class BooksController < ApplicationController
  def index
    @&#8203;books = Book.all
  end
end
```

```ruby
GET /books

SELECT * FROM books /application:MyApp;controller:books;action:index/

```

Custom tags containing static values and Procs can be defined in the application configuration:

```ruby
config.active_record.query_log_tags = [
  :application,
  :controller,
  :action,
  {
    custom_static: "foo",
    custom_dynamic: -> { Time.now }
  }
]
```

*Keeran Raj Hawoldar*, *Eileen M. Uchitelle*, *Kasper Timm Hansen*
  • Added support for multiple databases to rails db:setup and rails db:reset.

    Ryan Hall

  • Add ActiveRecord::Relation#structurally_compatible?.

    Adds a query method by which a user can tell if the relation that they're about to use for #or or #and is structurally compatible with the receiver.

    Kevin Newton

  • Add ActiveRecord::QueryMethods#in_order_of.

    This allows you to specify an explicit order that you'd like records returned in based on a SQL expression. By default, this will be accomplished using a case statement, as in:

    Post.in_order_of(:id, [3, 5, 1])

    will generate the SQL:

    SELECT "posts".* FROM "posts" ORDER BY CASE "posts"."id" WHEN 3 THEN 1 WHEN 5 THEN 2 WHEN 1 THEN 3 ELSE 4 END ASC

    However, because this functionality is built into MySQL in the form of the FIELD function, that connection adapter will generate the following SQL instead:

    SELECT "posts".* FROM "posts" ORDER BY FIELD("posts"."id", 1, 5, 3) DESC

    Kevin Newton

  • Fix eager_loading? when ordering with Symbol.

    eager_loading? is triggered correctly when using order with symbols.

    scope = Post.includes(:comments).order(:"comments.label")
    => true

    Jacopo Beschi

  • Two change tracking methods are added for belongs_to associations.

    The association_changed? method (assuming an association named :association) returns true if a different associated object has been assigned and the foreign key will be updated in the next save.

    The association_previously_changed? method returns true if the previous save updated the association to reference a different associated object.

    George Claghorn

  • Add option to disable schema dump per-database.

    Dumping the schema is on by default for all databases in an application. To turn it off for a specific database, use the schema_dump option:

config/database.yml

production:
  schema_dump: false
```

*Luis Vasconcellos*, *Eileen M. Uchitelle*
  • Fix eager_loading? when ordering with Hash syntax.

    eager_loading? is triggered correctly when using order with hash syntax on an outer table.

    Post.includes(:comments).order({ "comments.label": :ASC }).eager_loading?

=> true

```

*Jacopo Beschi*
  • Move the forcing of clear text encoding to the ActiveRecord::Encryption::Encryptor.

    Fixes #​42699.

    J Smith

  • partial_inserts is now disabled by default in new apps.

    This will be the default for new apps in Rails 7. To opt in:

    config.active_record.partial_inserts = true

    If a migration removes the default value of a column, this option would cause old processes to no longer be able to create new records.

    If you need to remove a column, you should first use ignored_columns to stop using it.

    Jean Boussier

  • Rails can now verify foreign keys after loading fixtures in tests.

    This will be the default for new apps in Rails 7. To opt in:

    config.active_record.verify_foreign_keys_for_fixtures = true

    Tests will not run if there is a foreign key constraint violation in your fixture data.

    The feature is supported by SQLite and PostgreSQL, other adapters can also add support for it.

    Alex Ghiculescu

  • Clear cached has_one association after setting belongs_to association to nil.

    After setting a belongs_to relation to nil and updating an unrelated attribute on the owner, the owner should still return nil on the has_one relation.

    Fixes #​42597.

    Michiel de Mare

  • OpenSSL constants are now used for Digest computations.

    Dirkjan Bussink

  • Adds support for if_not_exists to add_foreign_key and if_exists to remove_foreign_key.

    Applications can set their migrations to ignore exceptions raised when adding a foreign key that already exists or when removing a foreign key that does not exist.

    Example Usage:

    class AddAuthorsForeignKeyToArticles < ActiveRecord::Migration[7.0]
      def change
        add_foreign_key :articles, :authors, if_not_exists: true
      end
    end
    class RemoveAuthorsForeignKeyFromArticles < ActiveRecord::Migration[7.0]
      def change
        remove_foreign_key :articles, :authors, if_exists: true
      end
    end

    Roberto Miranda

  • Prevent polluting ENV during postgresql structure dump/load.

    Some configuration parameters were provided to pg_dump / psql via environment variables which persisted beyond the command being run, and may have caused subsequent commands and connections to fail. Tasks running across multiple postgresql databases like rails db:test:prepare may have been affected.

    Samuel Cochran

  • Set precision 6 by default for datetime columns.

    By default, datetime columns will have microseconds precision instead of seconds precision.

    Roberto Miranda

  • Allow preloading of associations with instance dependent scopes.

    John Hawthorn, John Crepezzi, Adam Hess, Eileen M. Uchitelle, Dinah Shi

  • Do not try to rollback transactions that failed due to a ActiveRecord::TransactionRollbackError.

    Jamie McCarthy

  • Active Record Encryption will now encode values as UTF-8 when using deterministic encryption. The encoding is part of the encrypted payload, so different encodings for different values result in different ciphertexts. This can break unique constraints and queries.

    The new behavior is configurable via active_record.encryption.forced_encoding_for_deterministic_encryption that is Encoding::UTF_8 by default. It can be disabled by setting it to nil.

    Jorge Manrubia

  • The MySQL adapter now cast numbers and booleans bind parameters to string for safety reasons.

    When comparing a string and a number in a query, MySQL converts the string to a number. So for instance "foo" = 0, will implicitly cast "foo" to 0 and will evaluate to TRUE which can lead to security vulnerabilities.

    Active Record already protect against that vulnerability when it knows the type of the column being compared, however until now it was still vulnerable when using bind parameters:

    User.where("login_token = ?", 0).first

    Would perform:

    SELECT * FROM `users` WHERE `login_token` = 0 LIMIT 1;

    Now it will perform:

    SELECT * FROM `users` WHERE `login_token` = '0' LIMIT 1;

    Jean Boussier

  • Fixture configurations (_fixture) are now strictly validated.

    If an error will be raised if that entry contains unknown keys while previously it would silently have no effects.

    Jean Boussier

  • Add ActiveRecord::Base.update! that works like ActiveRecord::Base.update but raises exceptions.

    This allows for the same behavior as the instance method #update! at a class level.

    Person.update!(:all, state: "confirmed")

    Dorian Marié

  • Add ActiveRecord::Base#attributes_for_database.

    Returns attributes with values for assignment to the database.

    Chris Salzberg

  • Use an empty query to check if the PostgreSQL connection is still active.

    An empty query is faster than SELECT 1.

    Heinrich Lee Yu

  • Add ActiveRecord::Base#previously_persisted?.

    Returns true if the object has been previously persisted but now it has been deleted.

  • Deprecate partial_writes in favor of partial_inserts and partial_updates.

    This allows to have a different behavior on update and create.

    Jean Boussier

  • Fix compatibility with psych >= 4.

    Starting in Psych 4.0.0 YAML.load behaves like YAML.safe_load. To preserve compatibility, Active Record's schema cache loader and YAMLColumn now uses YAML.unsafe_load if available.

    Jean Boussier

  • ActiveRecord::Base.logger is now a class_attribute.

    This means it can no longer be accessed directly through @@&#8203;logger, and that setting logger = on a subclass won't change the parent's logger.

    Jean Boussier

  • Add .asc.nulls_first for all databases. Unfortunately MySQL still doesn't like nulls_last.

    Keenan Brock

  • Improve performance of one? and many? by limiting the generated count query to 2 results.

    Gonzalo Riestra

  • Don't check type when using if_not_exists on add_column.

    Previously, if a migration called add_column with the if_not_exists option set to true the column_exists? check would look for a column with the same name and type as the migration.

    Recently it was discovered that the type passed to the migration is not always the same type as the column after migration. For example a column set to :mediumblob in the migration will be casted to binary when calling column.type. Since there is no straightforward way to cast the type to the database type without running the migration, we opted to drop the type check from add_column. This means that migrations adding a duplicate column with a different type will no longer raise an error.

    Eileen M. Uchitelle

  • Log a warning message when running SQLite in production.

    Using SQLite in production ENV is generally discouraged. SQLite is also the default adapter in a new Rails application. For the above reasons log a warning message when running SQLite in production.

    The warning can be disabled by setting config.active_record.sqlite3_production_warning=false.

    Jacopo Beschi

  • Add option to disable joins for has_one associations.

    In a multiple database application, associations can't join across databases. When set, this option instructs Rails to generate 2 or more queries rather than generating joins for has_one associations.

    Set the option on a has one through association:

    class Person
      has_one :dog
      has_one :veterinarian, through: :dog, disable_joins: true
    end

    Then instead of generating join SQL, two queries are used for @person.veterinarian:

    SELECT "dogs"."id" FROM "dogs" WHERE "dogs"."person_id" = ?  [["person_id", 1]]
    SELECT "veterinarians".* FROM "veterinarians" WHERE "veterinarians"."dog_id" = ?  [["dog_id", 1]]

    Sarah Vessels, Eileen M. Uchitelle

  • Arel::Visitors::Dot now renders a complete set of properties when visiting Arel::Nodes::SelectCore, SelectStatement, InsertStatement, UpdateStatement, and DeleteStatement, which fixes #​42026. Previously, some properties were omitted.

    Mike Dalessio

  • Arel::Visitors::Dot now supports Arel::Nodes::Bin, Case, CurrentRow, Distinct, DistinctOn, Else, Except, InfixOperation, Intersect, Lock, NotRegexp, Quoted, Regexp, UnaryOperation, Union, UnionAll, When, and With. Previously, these node types caused an exception to be raised by Arel::Visitors::Dot#accept.

    Mike Dalessio

  • Optimize remove_columns to use a single SQL statement.

    remove_columns :my_table, :col_one, :col_two

    Now results in the following SQL:

    ALTER TABLE "my_table" DROP COLUMN "col_one", DROP COLUMN "col_two"

    Jon Dufresne

  • Ensure has_one autosave association callbacks get called once.

    Change the has_one autosave callback to be non cyclic as well. By doing this the autosave callback are made more consistent for all 3 cases: has_many, has_one, and belongs_to.

    Petrik de Heus

  • Add option to disable joins for associations.

    In a multiple database application, associations can't join across databases. When set, this option instructs Rails to generate 2 or more queries rather than generating joins for associations.

    Set the option on a has many through association:

    class Dog
      has_many :treats, through: :humans, disable_joins: true
      has_many :humans
    end

    Then instead of generating join SQL, two queries are used for @dog.treats:

    SELECT "humans"."id" FROM "humans" WHERE "humans"."dog_id" = ?  [["dog_id", 1]]
    SELECT "treats".* FROM "treats" WHERE "treats"."human_id" IN (?, ?, ?)  [["human_id", 1], ["human_id", 2], ["human_id", 3]]

    Eileen M. Uchitelle, Aaron Patterson, Lee Quarella

  • Add setting for enumerating column names in SELECT statements.

    Adding a column to a PostgreSQL database, for example, while the application is running can change the result of wildcard SELECT * queries, which invalidates the result of cached prepared statements and raises a PreparedStatementCacheExpired error.

    When enabled, Active Record will avoid wildcards and always include column names in SELECT queries, which will return consistent results and avoid prepared statement errors.

    Before:

    Book.limit(5)

SELECT * FROM books LIMIT 5

```

After:

```ruby

config/application.rb

module MyApp
  class Application < Rails::Application
    config.active_record.enumerate_columns_in_select_statements = true
  end
end

or, configure per-model

class Book < ApplicationRecord
  self.enumerate_columns_in_select_statements = true
end
```

```ruby
Book.limit(5)

SELECT id, author_id, name, format, status, language, etc FROM books LIMIT 5

```

*Matt Duszynski*
  • Allow passing SQL as on_duplicate value to #upsert_all to make it possible to use raw SQL to update columns on conflict:

    Book.upsert_all(
      [{ id: 1, status: 1 }, { id: 2, status: 1 }],
      on_duplicate: Arel.sql("status = GREATEST(books.status, EXCLUDED.status)")
    )

    Vladimir Dementyev

  • Allow passing SQL as returning statement to #upsert_all:

    Article.insert_all(
      [
        { title: "Article 1", slug: "article-1", published: false },
        { title: "Article 2", slug: "article-2", published: false }
      ],
      returning: Arel.sql("id, (xmax = '0') as inserted, name as new_name")
    )

    Vladimir Dementyev

  • Deprecate legacy_connection_handling.

    Eileen M. Uchitelle

  • Add attribute encryption support.

    Encrypted attributes are declared at the model level. These are regular Active Record attributes backed by a column with the same name. The system will transparently encrypt these attributes before saving them into the database and will decrypt them when retrieving their values.

    class Person < ApplicationRecord
      encrypts :name
      encrypts :email_address, deterministic: true
    end

    You can learn more in the Active Record Encryption guide.

    Jorge Manrubia

  • Changed Arel predications contains and overlaps to use quoted_node so that PostgreSQL arrays are quoted properly.

    Bradley Priest

  • Add mode argument to record level strict_loading!.

    This argument can be used when enabling strict loading for a single record to specify that we only want to raise on n plus one queries.

    developer.strict_loading!(mode: :n_plus_one_only)
    
    developer.projects.to_a # Does not raise
    developer.projects.first.client # Raises StrictLoadingViolationError

    Previously, enabling strict loading would cause any lazily loaded association to raise an error. Using n_plus_one_only mode allows us to lazily load belongs_to, has_many, and other associations that are fetched through a single query.

    Dinah Shi

  • Fix Float::INFINITY assignment to datetime column with postgresql adapter.

    Before:

With this config

ActiveRecord::Base.time_zone_aware_attributes = true

and the following schema:

create_table "postgresql_infinities" do |t|
  t.datetime "datetime"
end

This test fails

record = PostgresqlInfinity.create!(datetime: Float::INFINITY)
assert_equal Float::INFINITY, record.datetime # record.datetime gets nil
```

After this commit, `record.datetime` gets `Float::INFINITY` as expected.

*Shunichi Ikegami*
  • Type cast enum values by the original attribute type.

    The notable thing about this change is that unknown labels will no longer match 0 on MySQL.

    class Book < ActiveRecord::Base
      enum :status, { proposed: 0, written: 1, published: 2 }
    end

    Before:

SELECT books.* FROM books WHERE books.status = 'prohibited' LIMIT 1

Book.find_by(status: :prohibited)

=> #<Book id: 1, status: "proposed", ...> (for mysql2 adapter)

=> ActiveRecord::StatementInvalid: PG::InvalidTextRepresentation: ERROR: invalid input syntax for type integer: "prohibited" (for postgresql adapter)

=> nil (for sqlite3 adapter)

```

After:

```ruby

SELECT books.* FROM books WHERE books.status IS NULL LIMIT 1

Book.find_by(status: :prohibited)

=> nil (for all adapters)

```

*Ryuta Kamizono*
  • Fixtures for has_many :through associations now load timestamps on join tables.

    Given this fixture:

monkeys.yml
george:
  name: George the Monkey
  fruits: apple
fruits.yml
apple:
  name: apple
```

If the join table (`fruit_monkeys`) contains `created_at` or `updated_at` columns,
these will now be populated when loading the fixture. Previously, fixture loading
would crash if these columns were required, and leave them as null otherwise.

*Alex Ghiculescu*
  • Allow applications to configure the thread pool for async queries.

    Some applications may want one thread pool per database whereas others want to use a single global thread pool for all queries. By default, Rails will set async_query_executor to nil which will not initialize any executor. If load_async is called and no executor has been configured, the query will be executed in the foreground.

    To create one thread pool for all database connections to use applications can set config.active_record.async_query_executor to :global_thread_pool and optionally define config.active_record.global_executor_concurrency. This defaults to 4. For applications that want to have a thread pool for each database connection, config.active_record.async_query_executor can be set to :multi_thread_pool. The configuration for each thread pool is set in the database configuration.

    Eileen M. Uchitelle

  • Allow new syntax for enum to avoid leading _ from reserved options.

    Before:

    class Book < ActiveRecord::Base
      enum status: [ :proposed, :written ], _prefix: true, _scopes: false
      enum cover: [ :hard, :soft ], _suffix: true, _default: :hard
    end

    After:

    class Book < ActiveRecord::Base
      enum :status, [ :proposed, :written ], prefix: true, scopes: false
      enum :cover, [ :hard, :soft ], suffix: true, default: :hard
    end

    Ryuta Kamizono

  • Add ActiveRecord::Relation#load_async.

    This method schedules the query to be performed asynchronously from a thread pool.

    If the result is accessed before a background thread had the opportunity to perform the query, it will be performed in the foreground.

    This is useful for queries that can be performed long enough before their result will be needed, or for controllers which need to perform several independent queries.

    def index
      @&#8203;categories = Category.some_complex_scope.load_async
      @&#8203;posts = Post.some_complex_scope.load_async
    end

    Active Record logs will also include timing info for the duration of how long the main thread had to wait to access the result. This timing is useful to know whether or not it's worth to load the query asynchronously.

    DEBUG -- :   Category Load (62.1ms)  SELECT * FROM `categories` LIMIT 50
    DEBUG -- :   ASYNC Post Load (64ms) (db time 126.1ms)  SELECT * FROM `posts` LIMIT 100

    The duration in the first set of parens is how long the main thread was blocked waiting for the results, and the second set of parens with "db time" is how long the entire query took to execute.

    Jean Boussier

  • Implemented ActiveRecord::Relation#excluding method.

    This method excludes the specified record (or collection of records) from the resulting relation:

    Post.excluding(post)
    Post.excluding(post_one, post_two)

    Also works on associations:

    post.comments.excluding(comment)
    post.comments.excluding(comment_one, comment_two)

    This is short-hand for Post.where.not(id: post.id) (for a single record) and Post.where.not(id: [post_one.id, post_two.id]) (for a collection).

    Glen Crawford

  • Skip optimised #exist? query when #include? is called on a relation with a having clause.

    Relations that have aliased select values AND a having clause that references an aliased select value would generate an error when #include? was called, due to an optimisation that would generate call #exists? on the relation instead, which effectively alters the select values of the query (and thus removes the aliased select values), but leaves the having clause intact. Because the having clause is then referencing an aliased column that is no longer present in the simplified query, an ActiveRecord::InvalidStatement error was raised.

    A sample query affected by this problem:

    Author.select('COUNT(*) as total_posts', 'authors.*')
          .joins(:posts)
          .group(:id)
          .having('total_posts > 2')
          .include?(Author.first)

    This change adds an addition check to the condition that skips the simplified #exists? query, which simply checks for the presence of a having clause.

    Fixes #​41417.

    Michael Smart

  • Increment postgres prepared statement counter before making a prepared statement, so if the statement is aborted without Rails knowledge (e.g., if app gets killed during long-running query or due to Rack::Timeout), app won't end up in perpetual crash state for being inconsistent with PostgreSQL.

    wbharding, Martin Tepper

  • Add ability to apply scoping to all_queries.

    Some applications may want to use the scoping method but previously it only worked on certain types of queries. This change allows the scoping method to apply to all queries for a model in a block.

    Post.where(blog_id: post.blog_id).scoping(all_queries: true) do
      post.update(title: "a post title") # adds `posts.blog_id = 1` to the query
    end

    Eileen M. Uchitelle

  • ActiveRecord::Calculations.calculate called with :average (aliased as ActiveRecord::Calculations.average) will now use column-based type casting. This means that floating-point number columns will now be aggregated as Float and decimal columns will be aggregated as BigDecimal.

    Integers are handled as a special case returning BigDecimal always (this was the case before already).

With the following schema:

create_table "measurements" do |t|
  t.float "temperature"
end

Before:

Measurement.average(:temperature).class

=> BigDecimal

After:

Measurement.average(:temperature).class

=> Float

```

Before this change, Rails just called `to_d` on average aggregates from the
database adapter. This is not the case anymore. If you relied on that kind
of magic, you now need to register your own `ActiveRecord::Type`
(see `ActiveRecord::Attributes::ClassMethods` for documentation).

*Josua Schmid*
  • PostgreSQL: introduce ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.datetime_type.

    This setting controls what native type Active Record should use when you call datetime in a migration or schema. It takes a symbol which must correspond to one of the configured NATIVE_DATABASE_TYPES. The default is :timestamp, meaning t.datetime in a migration will create a "timestamp without time zone" column. To use "timestamp with time zone", change this to :timestamptz in an initializer.

    You should run bin/rails db:migrate to rebuild your schema.rb if you change this.

    Alex Ghiculescu

  • PostgreSQL: handle timestamp with time zone columns correctly in schema.rb.

    Previously they dumped as t.datetime :column_name, now they dump as t.timestamptz :column_name, and are created as timestamptz columns when the schema is loaded.

    Alex Ghiculescu

  • Removing trailing whitespace when matching columns in ActiveRecord::Sanitization.disallow_raw_sql!.

    Gannon McGibbon, Adrian Hirt

  • Expose a way for applications to set a primary_abstract_class.

    Multiple database applications that use a primary abstract class that is not named ApplicationRecord can now set a specific class to be the primary_abstract_class.

    class PrimaryApplicationRecord
      self.primary_abstract_class
    end

    When an application boots it automatically connects to the primary or first database in the database configuration file. In a multiple database application that then call connects_to needs to know that the default connection is the same as the ApplicationRecord connection. However, some applications have a differently named ApplicationRecord. This prevents Active Record from opening duplicate connections to the same database.

    Eileen M. Uchitelle, John Crepezzi

  • Support hash config for structure_dump_flags and structure_load_flags flags. Now that Active Record supports multiple databases configuration, we need a way to pass specific flags for dump/load databases since the options are not the same for different adapters. We can use in the original way:

    ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = ['--no-defaults', '--skip-add-drop-table']

or

ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = '--no-defaults --skip-add-drop-table'
```

And also use it passing a hash, with one or more keys, where the key
is the adapter

```ruby
ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = {
  mysql2: ['--no-defaults', '--skip-add-drop-table'],
  postgres: '--no-tablespaces'
}
```

*Gustavo Gonzalez*
  • Connection specification now passes the "url" key as a configuration for the adapter if the "url" protocol is "jdbc", "http", or "https". Previously only urls with the "jdbc" prefix were passed to the Active Record Adapter, others are assumed to be adapter specification urls.

    Fixes #​41137.

    Jonathan Bracy

  • Allow to opt-out of strict_loading mode on a per-record base.

    This is useful when strict loading is enabled application wide or on a model level.

    class User < ApplicationRecord
      has_many :bookmarks
      has_many :articles, strict_loading: true
    end
    
    user = User.first
    user.articles                        # => ActiveRecord::StrictLoadingViolationError
    user.bookmarks                       # => #<ActiveRecord::Associations::CollectionProxy>
    
    user.strict_loading!(true)           # => true
    user.bookmarks                       # => ActiveRecord::StrictLoadingViolationError
    
    user.strict_loading!(false)          # => false
    user.bookmarks                       # => #<ActiveRecord::Associations::CollectionProxy>
    user.articles.strict_loading!(false) # => #<ActiveRecord::Associations::CollectionProxy>

    Ayrton De Craene

  • Add FinderMethods#sole and #find_sole_by to find and assert the presence of exactly one record.

    Used when you need a single row, but also want to assert that there aren't multiple rows matching the condition; especially for when database constraints aren't enough or are impractical.

    Product.where(["price = %?", price]).sole

=> ActiveRecord::RecordNotFound (if no Product with given price)

=> #<Product ...> (if one Product with given price)

=> ActiveRecord::SoleRecordExceeded (if more than one Product with given price)

user.api_keys.find_sole_by(key: key)

as above

```

*Asherah Connor*
  • Makes ActiveRecord::AttributeMethods::Query respect the getter overrides defined in the model.

    Before:

    class User
      def admin
        false # Overriding the getter to always return false
      end
    end
    
    user = User.first
    user.update(admin: true)
    
    user.admin # false (as expected, due to the getter overwrite)
    user.admin? # true (not expected, returned the DB column value)

    After this commit, user.admin? above returns false, as expected.

    Fixes #​40771.

    Felipe

  • Allow delegated_type to be specified primary_key and foreign_key.

    Since delegated_type assumes that the foreign_key ends with _id, singular_id defined by it does not work when the foreign_key does not end with id. This change fixes it by taking into account primary_key and foreign_key in the options.

    Ryota Egusa

  • Expose an invert_where method that will invert all scope conditions.

    class User
      scope :active, -> { where(accepted: true, locked: false) }
    end
    
    User.active

... WHERE accepted = 1 AND locked = 0

User.active.invert_where

... WHERE NOT (accepted = 1 AND locked = 0)

```

*Kevin Deisz*
  • Restore possibility of passing false to :polymorphic option of belongs_to.

    Previously, passing false would trigger the option validation logic to throw an error saying :polymorphic would not be a valid option.

    glaszig

  • Remove deprecated database kwarg from connected_to.

    Eileen M. Uchitelle, John Crepezzi

  • Allow adding nonnamed expression indexes to be revertible.

    Previously, the following code would raise an error, when executed while rolling back, and the index name should be specified explicitly. Now, the index name is inferred automatically.

    add_index(:items, "to_tsvector('english', description)")

    Fixes #​40732.

    fatkodima

  • Only warn about negative enums if a positive form that would cause conflicts exists.

    Fixes #​39065.

    Alex Ghiculescu

  • Add option to run default_scope on all queries.

    Previously, a default_scope would only run on select or insert queries. In some cases, like non-Rails tenant sharding solutions, it may be desirable to run default_scope on all queries in order to ensure queries are including a foreign key for the shard (i.e. blog_id).

    Now applications can add an option to run on all queries including select, insert, delete, and update by adding an all_queries option to the default scope definition.

    class Article < ApplicationRecord
      default_scope -> { where(blog_id: Current.blog.id) }, all_queries: true
    end

    Eileen M. Uchitelle

  • Add where.associated to check for the presence of an association.

Before:

account.users.joins(:contact).where.not(contact_id: nil)

After:

account.users.where.associated(:contact)
```

Also mirrors `where.missing`.

*Kasper Timm Hansen*
  • Allow constructors (build_association and create_association) on has_one :through associations.

    Santiago Perez Perret

Active Storage

  • Support transforming empty-ish has_many_attached value into [] (e.g. [""]).

    @&#8203;user.highlights = [""]
    @&#8203;user.highlights # => []

    Sean Doyle

  • Add ActiveStorage::Blob.compose to concatenate multiple blobs.

    Gannon McGibbon

  • Setting custom metadata on blobs are now persisted to remote storage.

    joshuamsager

  • Support direct uploads to multiple services.

    Dmitry Tsepelev

  • Invalid default content types are deprecated

    Blobs created with content_type image/jpg, image/pjpeg, image/bmp, text/javascript will now produce a deprecation warning, since these are not valid content types.

    These content types will be removed from the defaults in Rails 7.1.

    You can set config.active_storage.silence_invalid_content_types_warning = true to dismiss the warning.

    Alex Ghiculescu

  • Emit Active Support instrumentation events from Active Storage analyzers.

    Fixes #​42930

    Shouichi Kamiya

  • Add support for byte range requests

    Tom Prats

  • Attachments can be deleted after their association is no longer defined.

    Fixes #​42514

    Don Sisco

  • Make vips the default variant processor for new apps.

    See the upgrade guide for instructions on converting from mini_magick to vips. mini_magick is not deprecated, existing apps can keep using it.

    Breno Gazzola

  • Deprecate ActiveStorage::Current.host in favor of ActiveStorage::Current.url_options which accepts a host, protocol and port.

    Santiago Bartesaghi

  • Allow using IAM when signing URLs with GCS.

    gcs:
      service: GCS
      ...
      iam: true

    RRethy

  • OpenSSL constants are now used for Digest computations.

    Dirkjan Bussink

  • Deprecate config.active_storage.replace_on_assign_to_many. Future versions of Rails will behave the same way as when the config is set to true.

    Santiago Bartesaghi

  • Remove deprecated methods: build_after_upload, create_after_upload! in favor of create_and_upload!, and service_url in favor of url.

    Santiago Bartesaghi

  • Add support of strict_loading_by_default to ActiveStorage::Representations controllers.

    Anton Topchii, Andrew White

  • Allow to detach an attachment when record is not persisted.

    Jacopo Beschi

  • Use libvips instead of ImageMagick to analyze images when active_storage.variant_processor = vips.

    Breno Gazzola

  • Add metadata value for presence of video channel in video blobs.

    The metadata attribute of video blobs has a new boolean key named video that is set to true if the file has an video channel and false if it doesn't.

    Breno Gazzola

  • Deprecate usage of purge and purge_later from the association extension.

    Jacopo Beschi

  • Passing extra parameters in ActiveStorage::Blob#url to S3 Client.

    This allows calls of ActiveStorage::Blob#url to have more interaction with the S3 Presigner, enabling, amongst other options, custom S3 domain URL Generation.

    blob = ActiveStorage::Blob.last
    
    blob.url # => https://<bucket-name>.s3.<region>.amazonaws.com/<key>
    blob.url(virtual_host: true) # => # => https://<bucket-name>/<key>

    josegomezr

  • Allow setting a Cache-Control on files uploaded to GCS.

    gcs:
      service: GCS
      ...
      cache_control: "public, max-age=3600"

    maleblond

  • The parameters sent to ffmpeg for generating a video preview image are now configurable under config.active_storage.video_preview_arguments.

    Brendon Muir

  • The ActiveStorage video previewer will now use scene change detection to generate better preview images (rather than the previous default of using the first frame of the video). This change requires FFmpeg v3.4+.

    Jonathan Hefner

  • Add support for ActiveStorage expiring URLs.

    rails_blob_path(user.avatar, disposition: "attachment", expires_in: 30.minutes)
    
    <%= image_tag rails_blob_path(user.avatar.variant(resize: "100x100"), expires_in: 30.minutes) %>

    If you want to set default expiration time for ActiveStorage URLs throughout your application, set config.active_storage.urls_expire_in.

    aki77

  • Allow to purge an attachment when record is not persisted for has_many_attached.

    Jacopo Beschi

  • Add with_all_variant_records method to eager load all variant records on an attachment at once. with_attached_image scope now eager loads variant records if using variant tracking.

    Alex Ghiculescu

  • Add metadata value for presence of audio channel in video blobs.

    The metadata attribute of video blobs has a new boolean key named audio that is set to true if the file has an audio channel and false if it doesn't.

    Breno Gazzola

  • Adds analyzer for audio files.

    Breno Gazzola

  • Respect Active Record's primary_key_type in Active Storage migrations.

    fatkodima

  • Allow expires_in for ActiveStorage signed ids.

    aki77

  • Allow to purge an attachment when record is not persisted for has_one_attached.

    Jacopo Beschi

  • Add a load hook called active_storage_variant_record (providing ActiveStorage::VariantRecord) to allow for overriding aspects of the ActiveStorage::VariantRecord class. This makes ActiveStorage::VariantRecord consistent with ActiveStorage::Blob and ActiveStorage::Attachment that already have load hooks.

    Brendon Muir

  • ActiveStorage::PreviewError is raised when a previewer is unable to generate a preview image.

    Alex Robbin

  • Add ActiveStorage::Streaming module that can be included in a controller to get access to #send_blob_stream, which wraps the new ActionController::Base#send_stream method to stream a blob from cloud storage:

    class MyPublicBlobsController < ApplicationController
      include ActiveStorage::SetBlob, ActiveStorage::Streaming
    
      def show
        http_cache_forever(public: true) do
          send_blob_stream @&#8203;blob, disposition: params[:disposition]
        end
      end
    end

    DHH

  • Add ability to use pre-defined variants.

    class User < ActiveRecord::Base
      has_one_attached :avatar do |attachable|
        attachable.variant :thumb, resize: "100x100"
        attachable.variant :medium, resize: "300x300", monochrome: true
      end
    end
    
    class Gallery < ActiveRecord::Base
      has_many_attached :photos do |attachable|
        attachable.variant :thumb, resize: "100x100"
        attachable.variant :medium, resize: "300x300", monochrome: true
      end
    end
    
    <%= image_tag user.avatar.variant(:thumb) %>

    fatkodima

  • After setting config.active_storage.resolve_model_to_route = :rails_storage_proxy rails_blob_path and rails_representation_path will generate proxy URLs by default.

    Ali Ismayilov

  • Declare ActiveStorage::FixtureSet and ActiveStorage::FixtureSet.blob to improve fixture integration.

    Sean Doyle

Active Support

  • Fix ActiveSupport::Duration.build to support negative values.

    The algorithm to collect the parts of the ActiveSupport::Duration ignored the sign of the value and accumulated incorrect part values. This impacted ActiveSupport::Duration#sum (which is dependent on parts) but not ActiveSupport::Duration#eql? (which is dependent on value).

    Caleb Buxton, Braden Staudacher

  • Deprecate passing a format to #to_s in favor of #to_formatted_s in Array, Range, Date, DateTime, Time, BigDecimal, Float and, Integer.

    Rafael Mendonça França

  • Document ActiveSupport::Testing::Deprecation.

    Sam Bostock & Sam Jordan

  • Add Pathname#existence.

    Pathname.new("file").existence&.read

    Timo Schilling

  • Remove deprecate ActiveSupport::Multibyte::Unicode.default_normalization_form.

    Rafael Mendonça França

  • Remove deprecated support to use Range#include? to check the inclusion of a value in a date time range is deprecated.

    Rafael Mendonça França

  • Remove deprecated URI.parser.

    Rafael Mendonça França

  • Remove deprecated config.active_support.use_sha1_digests.

    Rafael Mendonça França

  • Invoking Object#with_options without a &block argument returns the ActiveSupport::OptionMerger instance.

    Sean Doyle

  • Rails.application.executor hooks can now be called around every test

    This helps to better simulate request or job local state being reset around tests and prevents state leaking from one test to another.

    However it requires the executor hooks executed in the test environment to be re-entrant.

    To enable this, set config.active_support.executor_around_test_case = true (this is the default in Rails 7).

    Jean Boussier

  • ActiveSupport::DescendantsTracker now mostly delegate to Class#descendants on Ruby 3.1

    Ruby now provides a fast Class#descendants making ActiveSupport::DescendantsTracker mostly useless.

    As a result the following methods are deprecated:

    • ActiveSupport::DescendantsTracker.direct_descendants
    • ActiveSupport::DescendantsTracker#direct_descendants

    Jean Boussier

  • Fix the Digest::UUID.uuid_from_hash behavior for namespace IDs that are different from the ones defined on Digest::UUID.

    The new behavior will be enabled by setting the config.active_support.use_rfc4122_namespaced_uuids option to true and is the default for new apps.

    The old behavior is the default for upgraded apps and will output a deprecation warning every time a value that is different than one of the constants defined on the Digest::UUID extension is used as the namespace ID.

    Alex Robbin, Erich Soares Machado, Eugene Kenny

  • ActiveSupport::Inflector::Inflections#clear(:acronyms) is now supported, and inflector.clear / inflector.clear(:all) also clears acronyms.

    Alex Ghiculescu, Oliver Peate

  • ActiveSupport::Dependencies no longer installs a const_missing hook. Before this, you could push to the autoload paths and have constants autoloaded. This feature, known as the classic autoloader, has been removed.

    Xavier Noria

  • Private internal classes of ActiveSupport::Dependencies have been deleted, like ActiveSupport::Dependencies::Reference, ActiveSupport::Dependencies::Blamable, and others.

    Xavier Noria

  • The private API of ActiveSupport::Dependencies has been deleted. That includes methods like hook!, unhook!, depend_on, require_or_load, mechanism, and many others.

    Xavier Noria

  • Improves the performance of ActiveSupport::NumberHelper formatters by avoiding the use of exceptions as flow control.

    Mike Dalessio

  • Removed rescue block from ActiveSupport::Cache::RedisCacheStore#handle_exception

    Previously, if you provided a error_handler to redis_cache_store, any errors thrown by the error handler would be rescued and logged only. Removed the rescue clause from handle_exception to allow these to be thrown.

    Nicholas A. Stuart

  • Allow entirely opting out of deprecation warnings.

    Previously if you did app.config.active_support.deprecation = :silence, some work would still be done on each call to ActiveSupport::Deprecation.warn. In very hot paths, this could cause performance issues.

    Now, you can make ActiveSupport::Deprecation.warn a no-op:

    config.active_support.report_deprecations = false

    This is the default in production for new apps. It is the equivalent to:

    config.active_support.deprecation = :silence
    config.active_support.disallowed_deprecation = :silence

    but will take a more optimised code path.

    Alex Ghiculescu

  • Faster tests by parallelizing only when overhead is justified by the number of them.

    Running tests in parallel adds overhead in terms of database setup and fixture loading. Now, Rails will only parallelize test executions when there are enough tests to make it worth it.

    This threshold is 50 by default, and is configurable via config setting in your test.rb:

    config.active_support.test_parallelization_threshold = 100

    It's also configurable at the test case level:

    class ActiveSupport::TestCase
      parallelize threshold: 100
    end

    Jorge Manrubia

  • OpenSSL constants are now used for Digest computations.

    Dirkjan Bussink

  • TimeZone.iso8601 now accepts valid ordinal values similar to Ruby's Date._iso8601 method. A valid ordinal value will be converted to an instance of TimeWithZone using the :year and :yday fragments returned from Date._iso8601.

    twz = ActiveSupport::TimeZone["Eastern Time (US & Canada)"].iso8601("21087")
    twz.to_a[0, 6] == [0, 0, 0, 28, 03, 2021]

    Steve Laing

  • Time#change and methods that call it (e.g. Time#advance) will now return a Time with the timezone argument provided, if the caller was initialized with a timezone argument.

    Fixes #​42467.

    Alex Ghiculescu

  • Allow serializing any module or class to JSON by name.

    Tyler Rick, Zachary Scott

  • Raise ActiveSupport::EncryptedFile::MissingKeyError when the RAILS_MASTER_KEY environment variable is blank (e.g. "").

    Sunny Ripert

  • The from: option is added to ActiveSupport::TestCase#assert_no_changes.

    It permits asserting on the initial value that is expected not to change.

    assert_no_changes -> { Status.all_good? }, from: true do
      post :create, params: { status: { ok: true } }
    end

    George Claghorn

  • Deprecate ActiveSupport::SafeBuffer's incorrect implicit conversion of objects into string.

    Except for a few methods like String#%, objects must implement #to_str to be implicitly converted to a String in string operations. In some circumstances ActiveSupport::SafeBuffer was incorrectly calling the explicit conversion method (#to_s) on them. This behavior is now deprecated.

    Jean Boussier

  • Allow nested access to keys on Rails.application.credentials.

    Previously only top level keys in credentials.yml.enc could be accessed with method calls. Now any key can.

    For example, given these secrets:

    aws:
      access_key_id: 123
      secret_access_key: 345

    Rails.application.credentials.aws.access_key_id will now return the same thing as Rails.application.credentials.aws[:access_key_id].

    Alex Ghiculescu

  • Added a faster and more compact ActiveSupport::Cache serialization format.

    It can be enabled with config.active_support.cache_format_version = 7.0 or config.load_defaults 7.0. Regardless of the configuration Active Support 7.0 can read cache entries serialized by Active Support 6.1 which allows to upgrade without invalidating the cache. However Rails 6.1 can't read the new format, so all readers must be upgraded before the new format is enabled.

    Jean Boussier

  • Add Enumerable#sole, per ActiveRecord::FinderMethods#sole. Returns the sole item of the enumerable, raising if no items are found, or if more than one is.

    Asherah Connor

  • Freeze ActiveSupport::Duration#parts and remove writer methods.

    Durations are meant to be value objects and should not be mutated.

    Andrew White

  • Fix ActiveSupport::TimeZone#utc_to_local with fractional seconds.

    When utc_to_local_returns_utc_offset_times is false and the time instance had fractional seconds the new UTC time instance was out by a factor of 1,000,000 as the Time.utc constructor takes a usec value and not a fractional second value.

    Andrew White

  • Add expires_at argument to ActiveSupport::Cache write and fetch to set a cache entry TTL as an absolute time.

    Rails.cache.write(key, value, expires_at: Time.now.at_end_of_hour)

    Jean Boussier

  • Deprecate ActiveSupport::TimeWithZone.name so that from Rails 7.1 it will use the default implementation.

    Andrew White

  • Deprecates Rails custom Enumerable#sum and Array#sum in favor of Ruby's native implementation which is considerably faster.

    Ruby requires an initializer for non-numeric type as per examples below:

    %w[foo bar].sum('')

instead of %w[foo bar].sum

[[1, 2], [3, 4, 5]].sum([])

instead of [[1, 2], [3, 4, 5]].sum

```

*Alberto Mota*
  • Tests parallelization is now disabled when running individual files to prevent the setup overhead.

    It can still be enforced if the environment variable PARALLEL_WORKERS is present and set to a value greater than 1.

    Ricardo Díaz

  • Fix proxying keyword arguments in ActiveSupport::CurrentAttributes.

    Marcin Kołodziej

  • Add Enumerable#maximum and Enumerable#minimum to easily calculate the maximum or minimum from extracted elements of an enumerable.

    payments = [Payment.new(5), Payment.new(15), Payment.new(10)]
    
    payments.minimum(:price) # => 5
    payments.maximum(:price) # => 15

    This also allows passing enumerables to fresh_when and stale? in Action Controller. See MR #​41404 for an example.

    Ayrton De Craene

  • ActiveSupport::Cache::MemCacheStore now accepts an explicit nil for its addresses argument.

    config.cache_store = :mem_cache_store, nil

is now equivalent to

config.cache_store = :mem_cache_store

and is also equivalent to

config.cache_store = :mem_cache_store, ENV["MEMCACHE_SERVERS"] || "localhost:11211"

which is the fallback behavior of Dalli

```

This helps those migrating from `:dalli_store`, where an explicit `nil` was permitted.

*Michael Overmeyer*
  • Add Enumerable#in_order_of to put an Enumerable in a certain order by a key.

    DHH

  • ActiveSupport::Inflector.camelize behaves expected when provided a symbol :upper or :lower argument. Matches String#camelize behavior.

    Alex Ghiculescu

  • Raises an ArgumentError when the first argument of ActiveSupport::Notification.subscribe is invalid.

    Vipul A M

  • HashWithIndifferentAccess#deep_transform_keys now returns a HashWithIndifferentAccess instead of a Hash.

    Nathaniel Woodthorpe

  • Consume dalli’s cache_nils configuration as ActiveSupport::Cache's skip_nil when using MemCacheStore.

    Ritikesh G

  • Add RedisCacheStore#stats method similar to MemCacheStore#stats. Calls redis#info internally.

    Ritikesh G

Guides

  • The autoloading guide for zeitwerk mode has been revised.

    Xavier Noria

  • The autoloading guide for classic mode has been deleted.

    Xavier Noria

Railtie

  • Allow localhost with a port by default in development

    [Fixes: #​43864]

  • Remove deprecated config in dbconsole.

    Rafael Mendonça França

  • Change default X-XSS-Protection header to disable XSS auditor

    This header has been deprecated and the XSS auditor it triggered has been removed from all major modern browsers (in favour of Content Security Policy) that implemented this header to begin with (Firefox never did).

    OWASP suggests setting this header to '0' to disable the default behaviour on old browsers as it can introduce additional security issues.

    Added the new behaviour as a framework default from Rails 7.0.

    Christian Sutter

  • Scaffolds now use date_field, time_field and datetime_field instead of date_select, time_select and datetime_select; thus providing native date/time pickers.

    Martijn Lafeber

  • Fix a regression in which autoload paths were initialized too late.

    Xavier Noria

  • Fix activestorage dependency in the npm package.

    Rafael Mendonça França

  • New and upgraded Rails apps no longer generate config/initializers/application_controller_renderer.rb or config/initializers/cookies_serializer.rb

    The default value for cookies_serializer (:json) has been moved to config.load_defaults("7.0"). The new framework defaults file can be used to upgrade the serializer.

    Alex Ghiculescu

  • New applications get a dependency on the new debug gem, replacing byebug.

    Xavier Noria

  • Add SSL support for postgresql in bin/rails dbconsole.

    Fixes #​43114.

    Michael Bayucot

  • Add support for comments above gem declaration in Rails application templates, e.g. gem("nokogiri", comment: "For XML").

    Linas Juškevičius

  • The setter config.autoloader= has been deleted. zeitwerk is the only available autoloading mode.

    Xavier Noria

  • config.autoload_once_paths can be configured in the body of the application class defined in config/application.rb or in the configuration for environments in config/environments/*.

    Similarly, engines can configure that collection in the class body of the engine class or in the configuration for environments.

    After that, the collection is frozen, and you can autoload from those paths. They are managed by the Rails.autoloaders.once autoloader, which does not reload, only autoloads/eager loads.

    Xavier Noria

  • During initialization, you cannot autoload reloadable classes or modules like application models, unless they are wrapped in a to_prepare block. For example, from config/initializers/*, or in application, engines, or railties initializers.

    Please check the autoloading guide for details.

    Xavier Noria

  • While they are allowed to have elements in common, it is no longer required that config.autoload_once_paths is a subset of config.autoload_paths. The former are managed by the once autoloader. The main autoloader manages the latter minus the former.

    Xavier Noria

  • Show Rake task description if command is run with -h.

    Adding -h (or --help) to a Rails command that's a Rake task now outputs the task description instead of the general Rake help.

    Petrik de Heus

  • Add missing plugin new command to help.

    *Petrik de Heus

  • Fix config_for error when there's only a shared root array.

    Loïc Delmaire

  • Raise an error in generators if an index type is invalid.

    Petrik de Heus

  • package.json now uses a strict version constraint for Rails JavaScript packages on new Rails apps.

    Zachary Scott, Alex Ghiculescu

  • Modified scaffold generator template so that running rails g scaffold Author no longer generates tests called "creating a Author", "updating a Author", and "destroying a Author".

    Fixes #​40744.

    Michael Duchemin

  • Raise an error in generators if a field type is invalid.

    Petrik de Heus

  • bin/rails tmp:clear deletes also files and directories in tmp/storage.

    George Claghorn

  • Fix compatibility with psych >= 4.

    Starting in Psych 4.0.0 YAML.load behaves like YAML.safe_load. To preserve compatibility Rails.application.config_for now uses YAML.unsafe_load if available.

    Jean Boussier

  • Allow loading nested locales in engines.

    Gannon McGibbon

  • Ensure Rails.application.config_for always cast hashes to ActiveSupport::OrderedOptions.

    Jean Boussier

  • Remove Rack::Runtime from the default middleware stack and deprecate referencing it in middleware operations without adding it back.

    Hartley McGuire

  • Allow adding additional authorized hosts in development via ENV['RAILS_DEVELOPMENT_HOSTS'].

    Josh Abernathy, Debbie Milburn

  • Add app concern and test keepfiles to generated engine plugins.

    Gannon McGibbon

  • Stop generating a license for in-app plugins.

    Gannon McGibbon

  • rails app:update no longer prompts you to overwrite files that are generally modified in the course of developing a Rails app. See #​41083 for the full list of changes.

    Alex Ghiculescu

  • Change default branch for new Rails projects and plugins to main.

    Prateek Choudhary

  • The new method Rails.benchmark gives you a quick way to measure and log the execution time taken by a block:

    def test_expensive_stuff
      Rails.benchmark("test_expensive_stuff") { ... }
    end

    This functionality was available in some contexts only before.

    Simon Perepelitsa

  • Applications generated with --skip-sprockets no longer get app/assets/config/manifest.js and app/assets/stylesheets/application.css.

    Cindy Gao

  • Add support for stylesheets and ERB views to rails stats.

    Joel Hawksley

  • Allow appended root routes to take precedence over internal welcome controller.

    Gannon McGibbon

v6.1.7.6

Compare Source

No changes between this and 6.1.7.5. This release was just to fix file permissions in the previous release.

v6.1.7.5: 6.1.7.5 Release

Compare Source

Active Support

  • Use a temporary file for storing unencrypted files while editing

    [CVE-2023-38037]

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • No changes.

Action Pack

  • No changes.

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.

v6.1.7.4

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • No changes.

Action Pack

  • Raise an exception if illegal characters are provide to redirect_to [CVE-2023-28362]

    Zack Deveau

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.

v6.1.7.3

Compare Source

Active Support

  • Implement SafeBuffer#bytesplice

    [CVE-2023-28120]

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • Ignore certain data-* attributes in rails-ujs when element is contenteditable

    [CVE-2023-23913]

Action Pack

  • No changes.

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.

v6.1.7.2

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • No changes.

Action Pack

  • Fix domain: :all for two letter TLD

    This fixes a compatibility issue introduced in our previous security release when using domain: :all with a two letter but single level top level domain domain (like .ca, rather than .co.uk).

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.

v6.1.7.1

Compare Source

Active Support

  • Avoid regex backtracking in Inflector.underscore

    [CVE-2023-22796]

Active Model

  • No changes.

Active Record

  • Make sanitize_as_sql_comment more strict

    Though this method was likely never meant to take user input, it was attempting sanitization. That sanitization could be bypassed with carefully crafted input.

    This commit makes the sanitization more robust by replacing any occurrances of "/" or "/" with "/ " or " /". It also performs a first pass to remove one surrounding comment to avoid compatibility issues for users relying on the existing removal.

    This also clarifies in the documentation of annotate that it should not be provided user input.

    [CVE-2023-22794]

  • Added integer width check to PostgreSQL::Quoting

    Given a value outside the range for a 64bit signed integer type PostgreSQL will treat the column type as numeric. Comparing integer values against numeric values can result in a slow sequential scan.

    This behavior is configurable via ActiveRecord::Base.raise_int_wider_than_64bit which defaults to true.

    [CVE-2022-44566]

Action View

  • No changes.

Action Pack

  • Avoid regex backtracking on If-None-Match header

    [CVE-2023-22795]

  • Use string#split instead of regex for domain parts

    [CVE-2023-22792]

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.

v6.1.7

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • Symbol is allowed by default for YAML columns

    Étienne Barrié

  • Fix ActiveRecord::Store to serialize as a regular Hash

    Previously it would serialize as an ActiveSupport::HashWithIndifferentAccess which is wasteful and cause problem with YAML safe_load.

    Jean Boussier

  • Fix PG.connect keyword arguments deprecation warning on ruby 2.7

    Fixes #​44307.

    Nikita Vasilevsky

Action View

  • No changes.

Action Pack

  • No changes.

Active Job

  • No changes.

Action Mailer

  • No changes.

Action Cable

  • No changes.

Active Storage

  • Respect Active Record's primary_key_type in Active Storage migrations. Backported from 7.0.

    fatkodima

Action Mailbox

  • No changes.

Action Text

  • No changes.

Railties

  • No changes.

v6.1.6.1: 6.1.6.1

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • Change ActiveRecord::Coders::YAMLColumn default to safe_load

    This adds two new configuration options The configuration options are as follows:

    • config.active_storage.use_yaml_unsafe_load

    When set to true, this configuration option tells Rails to use the old "unsafe" YAML loading strategy, maintaining the existing behavior but leaving the possible escalation vulnerability in place. Setting this option to true is not recommended, but can aid in upgrading.

    • config.active_record.yaml_column_permitted_classes

    The "safe YAML" loading method does not allow all classes to be deserialized by default. This option allows you to specify classes deemed "safe" in your application. For example, if your application uses Symbol and Time in serialized data, you can add Symbol and Time to the allowed list as follows:

    config.active_record.yaml_column_permitted_classes = [Symbol, Date, Time]

    [CVE-2022-32224]

Action View

  • No changes.

Action Pack

  • No changes.

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.

v6.1.6: 6.1.6

Compare Source

Active Support

  • Fix and add protections for XSS in ActionView::Helpers and ERB::Util.

    Add the method ERB::Util.xml_name_escape to escape dangerous characters in names of tags and names of attributes, following the specification of XML.

    Álvaro Martín Fraguas

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • Fix and add protections for XSS in ActionView::Helpers and ERB::Util.

    Escape dangerous characters in names of tags and names of attributes in the tag helpers, following the XML specification. Rename the option :escape_attributes to :escape, to simplify by applying the option to the whole tag.

    Álvaro Martín Fraguas

Action Pack

  • Allow Content Security Policy DSL to generate for API responses.

    Tim Wade

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.

v6.1.5.1: 6.1.5.1

Compare Source

Active Support

  • Fix and add protections for XSS in ActionView::Helpers and ERB::Util.

    Add the method ERB::Util.xml_name_escape to escape dangerous characters in names of tags and names of attributes, following the specification of XML.

    Álvaro Martín Fraguas

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • Fix and add protections for XSS in ActionView::Helpers and ERB::Util.

    Escape dangerous characters in names of tags and names of attributes in the tag helpers, following the XML specification. Rename the option :escape_attributes to :escape, to simplify by applying the option to the whole tag.

    Álvaro Martín Fraguas

Action Pack

  • Allow Content Security Policy DSL to generate for API responses.

    Tim Wade

Active Job

  • No changes.

Action Mailer

  • No changes.

Action Cable

  • No changes.

Active Storage

  • No changes.

Railties

  • No changes.

v6.1.5: 6.1.5

Compare Source

Active Support

  • Fix ActiveSupport::Duration.build to support negative values.

    The algorithm to collect the parts of the ActiveSupport::Duration ignored the sign of the value and accumulated incorrect part values. This impacted ActiveSupport::Duration#sum (which is dependent on parts) but not ActiveSupport::Duration#eql? (which is dependent on value).

    Caleb Buxton, Braden Staudacher

  • Time#change and methods that call it (eg. Time#advance) will now return a Time with the timezone argument provided, if the caller was initialized with a timezone argument.

    Fixes #​42467.

    Alex Ghiculescu

  • Clone to keep extended Logger methods for tagged logger.

    Orhan Toy

  • assert_changes works on including ActiveSupport::Assertions module.

    Pedro Medeiros

Active Model

  • Clear secure password cache if password is set to nil

    Before:

    user.password = 'something' user.password = nil

    user.password # => 'something'

    Now:

    user.password = 'something' user.password = nil

    user.password # => nil

    Markus Doits

  • Fix delegation in ActiveModel::Type::Registry#lookup and ActiveModel::Type.lookup

    Passing a last positional argument {} would be incorrectly considered as keyword argument.

    Benoit Daloze

  • Fix to_json after changes_applied for ActiveModel::Dirty object.

    Ryuta Kamizono

Active Record

  • Fix ActiveRecord::ConnectionAdapters::SchemaCache#deep_deduplicate for Ruby 2.6.

    Ruby 2.6 and 2.7 have slightly different implementations of the String#@&#8203;- method. In Ruby 2.6, the receiver of the String#@&#8203;- method is modified under certain circumstances. This was later identified as a bug (https://bugs.ruby-lang.org/issues/15926) and only fixed in Ruby 2.7.

    Before the changes in this commit, the ActiveRecord::ConnectionAdapters::SchemaCache#deep_deduplicate method, which internally calls the String#@&#8203;- method, could also modify an input string argument in Ruby 2.6 -- changing a tainted, unfrozen string into a tainted, frozen string.

    Fixes #​43056

    Eric O'Hanlon

  • Fix migration compatibility to create SQLite references/belongs_to column as integer when migration version is 6.0.

    reference/belongs_to in migrations with version 6.0 were creating columns as bigint instead of integer for the SQLite Adapter.

    Marcelo Lauxen

  • Fix dbconsole for 3-tier config.

    Eileen M. Uchitelle

  • Better handle SQL queries with invalid encoding.

    Post.create(name: "broken \xC8 UTF-8")

    Would cause all adapters to fail in a non controlled way in the code responsible to detect write queries.

    The query is now properly passed to the database connection, which might or might not be able to handle it, but will either succeed or failed in a more correct way.

    Jean Boussier

  • Ignore persisted in-memory records when merging target lists.

    Kevin Sjöberg

  • Fix regression bug that caused ignoring additional conditions for preloading has_many through relations.

    Fixes #​43132

    Alexander Pauly

  • Fix ActiveRecord::InternalMetadata to not be broken by config.active_record.record_timestamps = false

    Since the model always create the timestamp columns, it has to set them, otherwise it breaks various DB management tasks.

    Fixes #​42983

    Jean Boussier

  • Fix duplicate active record objects on inverse_of.

    Justin Carvalho

  • Fix duplicate objects stored in has many association after save.

    Fixes #​42549.

    Alex Ghiculescu

  • Fix performance regression in CollectionAssocation#build.

    Alex Ghiculescu

  • Fix retrieving default value for text column for MariaDB.

    fatkodima

Action View

  • preload_link_tag properly inserts as attributes for files with image MIME types, such as JPG or SVG.

    Nate Berkopec

  • Add autocomplete="off" to all generated hidden fields.

    Fixes #​42610.

    Ryan Baumann

  • Fix current_page? when URL has trailing slash.

    This fixes the current_page? helper when the given URL has a trailing slash, and is an absolute URL or also has query params.

    Fixes #​33956.

    Jonathan Hefner

Action Pack

  • Fix content_security_policy returning invalid directives.

    Directives such as self, unsafe-eval and few others were not single quoted when the directive was the result of calling a lambda returning an array.

    content_security_policy do |policy|
      policy.frame_ancestors lambda { [:self, "https://example.com"] }
    end

    With this fix the policy generated from above will now be valid.

    Edouard Chin

  • Update HostAuthorization middleware to render debug info only when config.consider_all_requests_local is set to true.

    Also, blocked host info is always logged with level error.

    Fixes #​42813.

    Nikita Vyrko

  • Dup arrays that get "converted".

    Fixes #​43681.

    Aaron Patterson

  • Don't show deprecation warning for equal paths.

    Anton Rieder

  • Fix crash in ActionController::Instrumentation with invalid HTTP formats.

    Fixes #​43094.

    Alex Ghiculescu

  • Add fallback host for SystemTestCase driven by RackTest.

    Fixes #​42780.

    Petrik de Heus

  • Add more detail about what hosts are allowed.

    Alex Ghiculescu

Active Job

  • No changes.

Action Mailer

  • No changes.

Action Cable

  • The Action Cable client now ensures successful channel subscriptions:

    • The client maintains a set of pending subscriptions until either the server confirms the subscription or the channel is torn down.
    • Rectifies the race condition where an unsubscribe is rapidly followed by a subscribe (on the same channel identifier) and the requests are handled out of order by the ActionCable server, thereby ignoring the subscribe command.

    Daniel Spinosa

  • Truncate broadcast logging messages.

    J Smith

Active Storage

  • Attachments can be deleted after their association is no longer defined.

    Fixes #​42514

    Don Sisco

Action Mailbox

  • Add attachments to the list of permitted parameters for inbound emails conductor.

    When using the conductor to test inbound emails with attachments, this prevents an unpermitted parameter warning in default configurations, and prevents errors for applications that set:

    config.action_controller.action_on_unpermitted_parameters = :raise

    David Jones, Dana Henke

Action Text

  • Fix Action Text extra trix content wrapper.

    Alexandre Ruban

Railties

  • In zeitwerk mode, setup the once autoloader first, and the main autoloader after it. This order plays better with shared namespaces.

    Xavier Noria

  • Handle paths with spaces when editing credentials.

    Alex Ghiculescu

  • Support Psych 4 when loading secrets.

    Nat Morcos

v6.1.4.7: 6.1.4.7

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • No changes.

Action Pack

  • No changes.

Active Job

  • No changes.

Action Mailer

  • No changes.

Action Cable

  • No changes.

Active Storage

  • Added image transformation validation via configurable allow-list.

    Variant now offers a configurable allow-list for transformation methods in addition to a configurable deny-list for arguments.

    [CVE-2022-21831]

Action Mailbox

  • No changes.

Action Text

  • No changes.

Railties

  • No changes.

v6.1.4.6: 6.1.4.6

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • No changes.

Action Pack

  • Fix Reloader method signature to work with the new Executor signature

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.

v6.1.4.5: 6.1.4.5

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • No changes.

Action Pack

  • Under certain circumstances, the middleware isn't informed that the response body has been fully closed which result in request state not being fully reset before the next request

    [CVE-2022-23633]

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.

v6.1.4.4: 6.1.4.4

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • No changes.

Action Pack

  • Fix issue with host protection not allowing host with port in development.

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.

v6.1.4.3: 6.1.4.3

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • No changes.

Action Pack

  • No changes.

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

  • Allow localhost with a port by default in development

    [Fixes: #​43864]

v6.1.4.2: 6.1.4.2

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • No changes.

Action Pack

  • Fix X_FORWARDED_HOST protection. [CVE-2021-44528]

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.

v6.1.4.1

Compare Source

v6.1.4: 6.1.4

Compare Source

Active Support

  • MemCacheStore: convert any underlying value (including false) to an Entry.

    See #​42559.

    Alex Ghiculescu

  • Fix bug in number_with_precision when using large BigDecimal values.

    Fixes #​42302.

    Federico Aldunate, Zachary Scott

  • Check byte size instead of length on secure_compare.

    Tietew

  • Fix Time.at to not lose :in option.

    Ryuta Kamizono

  • Require a path for config.cache_store = :file_store.

    Alex Ghiculescu

  • Avoid having to store complex object in the default translation file.

    Rafael Mendonça França

Active Model

  • Fix to_json for ActiveModel::Dirty object.

    Exclude +mutations_from_database+ attribute from json as it lead to recursion.

    Anil Maurya

Active Record

  • Do not try to rollback transactions that failed due to a ActiveRecord::TransactionRollbackError.

    Jamie McCarthy

  • Raise an error if pool_config is nil in set_pool_config.

    Eileen M. Uchitelle

  • Fix compatibility with psych >= 4.

    Starting in Psych 4.0.0 YAML.load behaves like YAML.safe_load. To preserve compatibility Active Record's schema cache loader and YAMLColumn now uses YAML.unsafe_load if available.

    Jean Boussier

  • Support using replicas when using rails dbconsole.

    Christopher Thornton

  • Restore connection pools after transactional tests.

    Eugene Kenny

  • Change upsert_all to fails cleanly for MySQL when :unique_by is used.

    Bastian Bartmann

  • Fix user-defined self.default_scope to respect table alias.

    Ryuta Kamizono

  • Clear @cache_keys cache after update_all, delete_all, destroy_all.

    Ryuta Kamizono

  • Changed Arel predications contains and overlaps to use quoted_node so that PostgreSQL arrays are quoted properly.

    Bradley Priest

  • Fix merge when the where clauses have string contents.

    Ryuta Kamizono

  • Fix rollback of parent destruction with nested dependent: :destroy.

    Jacopo Beschi

  • Fix binds logging for "WHERE ... IN ..." statements.

    Ricardo Díaz

  • Handle false in relation strict loading checks.

    Previously when a model had strict loading set to true and then had a relation set strict_loading to false the false wasn't considered when deciding whether to raise/warn about strict loading.

    class Dog < ActiveRecord::Base
      self.strict_loading_by_default = true
    
      has_many :treats, strict_loading: false
    end

    In the example, dog.treats would still raise even though strict_loading was set to false. This is a bug effecting more than Active Storage which is why I made this MR superceeding #​41461. We need to fix this for all applications since the behavior is a little surprising. I took the test from ##​41461 and the code suggestion from #​41453 with some additions.

    Eileen M. Uchitelle, Radamés Roriz

  • Fix numericality validator without precision.

    Ryuta Kamizono

  • Fix aggregate attribute on Enum types.

    Ryuta Kamizono

  • Fix CREATE INDEX statement generation for PostgreSQL.

    eltongo

  • Fix where clause on enum attribute when providing array of strings.

    Ryuta Kamizono

  • Fix unprepared_statement to work it when nesting.

    Ryuta Kamizono

Action View

  • The translate helper now passes default values that aren't translation keys through I18n.translate for interpolation.

    Jonathan Hefner

  • Don't attach UJS form submission handlers to Turbo forms.

    David Heinemeier Hansson

  • Allow both current_page?(url_hash) and current_page?(**url_hash) on Ruby 2.7.

    Ryuta Kamizono

Action Pack

  • Ignore file fixtures on db:fixtures:load

    Kevin Sjöberg

  • Fix ActionController::Live controller test deadlocks by removing the body buffer size limit for tests.

    Dylan Thacker-Smith

  • Correctly place optional path parameter booleans.

    Previously, if you specify a url parameter that is part of the path as false it would include that part of the path as parameter for example:

    get "(/optional/:optional_id)/things" => "foo#foo", as: :things
    things_path(optional_id: false) # => /things?optional_id=false

    After this change, true and false will be treated the same when used as optional path parameters. Meaning now:

    get '(this/:my_bool)/that' as: :that
    
    that_path(my_bool: true) # => `/this/true/that`
    that_path(my_bool: false) # => `/this/false/that`

    Adam Hess

  • Add support for 'private, no-store' Cache-Control headers.

    Previously, 'no-store' was exclusive; no other directives could be specified.

    Alex Smith

Active Job

  • No changes.

Action Mailer

  • No changes.

Action Cable

  • Fix ArgumentError with ruby 3.0 on RemoteConnection#disconnect.

    Vladislav

Active Storage

  • The parameters sent to ffmpeg for generating a video preview image are now configurable under config.active_storage.video_preview_arguments.

    Brendon Muir

  • Fix Active Storage update task when running in an engine.

    Justin Malčić*

  • Don't raise an error if the mime type is not recognized.

    Fixes #​41777.

    Alex Ghiculescu

  • ActiveStorage::PreviewError is raised when a previewer is unable to generate a preview image.

    Alex Robbin

  • respond with 404 given invalid variation key when asking for representations.

    George Claghorn

  • Blob creation shouldn't crash if no service selected.

    Alex Ghiculescu

Action Mailbox

  • No changes.

Action Text

  • Always render attachment partials as HTML with :html format inside trix editor.

    James Brooks

Railties

  • Fix compatibility with psych >= 4.

    Starting in Psych 4.0.0 YAML.load behaves like YAML.safe_load. To preserve compatibility Rails.application.config_for now uses YAML.unsafe_load if available.

    Jean Boussier

  • Ensure Rails.application.config_for always cast hashes to ActiveSupport::OrderedOptions.

    Jean Boussier

  • Fix create migration generator with --pretend option.

    euxx

v6.1.3.2: 6.1.3.2

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • No changes.

Action Pack

  • Prevent open redirects by correctly escaping the host allow list CVE-2021-22903

  • Prevent catastrophic backtracking during mime parsing CVE-2021-22902

  • Prevent regex DoS in HTTP token authentication CVE-2021-22904

  • Prevent string polymorphic route arguments.

    url_for supports building polymorphic URLs via an array of arguments (usually symbols and records). If a developer passes a user input array, strings can result in unwanted route helper calls.

    CVE-2021-22885

    Gannon McGibbon

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.

v6.1.3.1: 6.1.3.1

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • No changes.

Action Pack

  • No changes.

Active Job

  • No changes.

Action Mailer

  • No changes.

Action Cable

  • No changes.

Active Storage

  • Marcel is upgraded to version 1.0.0 to avoid a dependency on GPL-licensed mime types data.

    George Claghorn

Action Mailbox

  • No changes.

Action Text

  • No changes.

Railties

  • No changes.

v6.1.3: 6.1.3

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • Fix the MySQL adapter to always set the right collation and charset to the connection session.

    Rafael Mendonça França

  • Fix MySQL adapter handling of time objects when prepared statements are enabled.

    Rafael Mendonça França

  • Fix scoping in enum fields using conditions that would generate an IN clause.

    Ryuta Kamizono

  • Skip optimised #exist? query when #include? is called on a relation with a having clause

    Relations that have aliased select values AND a having clause that references an aliased select value would generate an error when #include? was called, due to an optimisation that would generate call #exists? on the relation instead, which effectively alters the select values of the query (and thus removes the aliased select values), but leaves the having clause intact. Because the having clause is then referencing an aliased column that is no longer present in the simplified query, an ActiveRecord::InvalidStatement error was raised.

    An sample query affected by this problem:

    Author.select('COUNT(*) as total_posts', 'authors.*')
          .joins(:posts)
          .group(:id)
          .having('total_posts > 2')
          .include?(Author.first)

    This change adds an addition check to the condition that skips the simplified #exists? query, which simply checks for the presence of a having clause.

    Fixes #​41417

    Michael Smart

  • Increment postgres prepared statement counter before making a prepared statement, so if the statement is aborted without Rails knowledge (e.g., if app gets kill -9d during long-running query or due to Rack::Timeout), app won't end up in perpetual crash state for being inconsistent with Postgres.

    wbharding, Martin Tepper

Action View

  • No changes.

Action Pack

  • Re-define routes when not set correctly via inheritance.

    John Hawthorn

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.

v6.1.2.1: 6.1.2.1

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • Fix possible DoS vector in PostgreSQL money type

    Carefully crafted input can cause a DoS via the regular expressions used for validating the money format in the PostgreSQL adapter. This patch fixes the regexp.

    Thanks to @​dee-see from Hackerone for this patch!

    [CVE-2021-22880]

    Aaron Patterson

Action View

  • No changes.

Action Pack

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.

v6.1.2: 6.1.2

Compare Source

Active Support

  • ActiveSupport::Cache::MemCacheStore now accepts an explicit nil for its addresses argument.

    config.cache_store = :mem_cache_store, nil

is now equivalent to

config.cache_store = :mem_cache_store

and is also equivalent to

config.cache_store = :mem_cache_store, ENV["MEMCACHE_SERVERS"] || "localhost:11211"

which is the fallback behavior of Dalli

```

This helps those migrating from `:dalli_store`, where an explicit `nil` was permitted.

*Michael Overmeyer*

Active Model

  • No changes.

Active Record

  • Fix timestamp type for sqlite3.

    Eileen M. Uchitelle

  • Make destroy async transactional.

    An active record rollback could occur while enqueuing a job. In this case the job would enqueue even though the database deletion rolledback putting things in a funky state.

    Now the jobs are only enqueued until after the db transaction has been committed.

    Cory Gwin

  • Fix malformed packet error in MySQL statement for connection configuration.

    robinroestenburg

  • Connection specification now passes the "url" key as a configuration for the adapter if the "url" protocol is "jdbc", "http", or "https". Previously only urls with the "jdbc" prefix were passed to the Active Record Adapter, others are assumed to be adapter specification urls.

    Fixes #​41137.

    Jonathan Bracy

  • Fix granular connection swapping when there are multiple abstract classes.

    Eileen M. Uchitelle

  • Fix find_by with custom primary key for belongs_to association.

    Ryuta Kamizono

  • Add support for rails console --sandbox for multiple database applications.

    alpaca-tc

  • Fix where on polymorphic association with empty array.

    Ryuta Kamizono

  • Fix preventing writes for ApplicationRecord.

    Eileen M. Uchitelle

Action View

  • No changes.

Action Pack

  • Fix error in ActionController::LogSubscriber that would happen when throwing inside a controller action.

    Janko Marohnić

  • Fix fixture_file_upload deprecation when file_fixture_path is a relative path.

    Eugene Kenny

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.

v6.1.1: 6.1.1

Compare Source

Active Support

  • Change IPAddr#to_json to match the behavior of the json gem returning the string representation instead of the instance variables of the object.

    Before:

    IPAddr.new("127.0.0.1").to_json

=> "{"addr":2130706433,"family":2,"mask_addr":4294967295}"

```

After:

```ruby
IPAddr.new("127.0.0.1").to_json

=> ""127.0.0.1""

```

Active Model

  • No changes.

Active Record

  • Fix fixtures loading when strict loading is enabled for the association.

    Alex Ghiculescu

  • Fix where with custom primary key for belongs_to association.

    Ryuta Kamizono

  • Fix where with aliased associations.

    Ryuta Kamizono

  • Fix composed_of with symbol mapping.

    Ryuta Kamizono

  • Don't skip money's type cast for pluck and calculations.

    Ryuta Kamizono

  • Fix where on polymorphic association with non Active Record object.

    Ryuta Kamizono

  • Make sure db:prepare works even the schema file doesn't exist.

    Rafael Mendonça França

  • Fix complicated has_many :through with nested where condition.

    Ryuta Kamizono

  • Handle STI models for has_many dependent: :destroy_async.

    Muhammad Usman

  • Restore possibility of passing false to :polymorphic option of belongs_to.

    Previously, passing false would trigger the option validation logic to throw an error saying :polymorphic would not be a valid option.

    glaszig

  • Allow adding nonnamed expression indexes to be revertible.

    Fixes #​40732.

    Previously, the following code would raise an error, when executed while rolling back, and the index name should be specified explicitly. Now, the index name is inferred automatically.

    add_index(:items, "to_tsvector('english', description)")

    fatkodima

Action View

  • Fix lazy translation in partial with block.

    Marek Kasztelnik

  • Avoid extra SELECT COUNT queries when rendering Active Record collections.

    aar0nr

  • Link preloading keep integrity hashes in the header.

    Étienne Barrié

  • Add config.action_view.preload_links_header to allow disabling of the Link header being added by default when using stylesheet_link_tag and javascript_include_tag.

    Andrew White

  • The translate helper now resolves default values when a nil key is specified, instead of always returning nil.

    Jonathan Hefner

Action Pack

  • Fix nil translation key lookup in controllers/

    Jan Klimo

  • Quietly handle unknown HTTP methods in Action Dispatch SSL middleware.

    Alex Robbin

  • Change the request method to a GET when passing failed requests down to config.exceptions_app.

    Alex Robbin

Active Job

  • Make retry_job return the job that was created.

    Rafael Mendonça França

  • Include ActiveSupport::Testing::Assertions in ActiveJob::TestHelpers.

    Mikkel Malmberg

Action Mailer

  • Sets default mailer queue to "default" in the mail assertions.

    Paul Keen

Action Cable

  • No changes.

Active Storage

  • Fix S3 multipart uploads when threshold is larger than file.

    Matt Muller

Action Mailbox

  • No changes.

Action Text

  • No changes.

Railties

  • Allow spaces in path to Yarn binstub and only run on precompile if needed.

    Markus Doits

  • Populate ARGV for app template.

    Fixes #​40945.

    Jonathan Hefner

v6.1.0: 6.1.0

Compare Source

Active Support

  • Ensure MemoryStore disables compression by default. Reverts behavior of MemoryStore to its prior rails 5.1 behavior.

    Max Gurewitz

  • Calling iso8601 on negative durations retains the negative sign on individual digits instead of prepending it.

    This change is required so we can interoperate with PostgreSQL, which prefers negative signs for each component.

    Compatibility with other iso8601 parsers which support leading negatives as well as negatives per component is still retained.

    Before:

    (-1.year - 1.day).iso8601

=> "-P1Y1D"

After:

    (-1.year - 1.day).iso8601

=> "P-1Y-1D"

*Vipul A M*
  • Remove deprecated ActiveSupport::Notifications::Instrumenter#end=.

    Rafael Mendonça França

  • Deprecate ActiveSupport::Multibyte::Unicode.default_normalization_form.

    Rafael Mendonça França

  • Remove deprecated ActiveSupport::Multibyte::Unicode.pack_graphemes, ActiveSupport::Multibyte::Unicode.unpack_graphemes, ActiveSupport::Multibyte::Unicode.normalize, ActiveSupport::Multibyte::Unicode.downcase, ActiveSupport::Multibyte::Unicode.upcase and ActiveSupport::Multibyte::Unicode.swapcase.

    Rafael Mendonça França

  • Remove deprecated ActiveSupport::Multibyte::Chars#consumes? and ActiveSupport::Multibyte::Chars#normalize.

    Rafael Mendonça França

  • Remove deprecated file active_support/core_ext/range/include_range.

    Rafael Mendonça França

  • Remove deprecated file active_support/core_ext/hash/transform_values.

    Rafael Mendonça França

  • Remove deprecated file active_support/core_ext/hash/compact.

    Rafael Mendonça França

  • Remove deprecated file active_support/core_ext/array/prepend_and_append.

    Rafael Mendonça França

  • Remove deprecated file active_support/core_ext/numeric/inquiry.

    Rafael Mendonça França

  • Remove deprecated file active_support/core_ext/module/reachable.

    Rafael Mendonça França

  • Remove deprecated Module#parent_name, Module#parent and Module#parents.

    Rafael Mendonça França

  • Remove deprecated ActiveSupport::LoggerThreadSafeLevel#after_initialize.

    Rafael Mendonça França

  • Remove deprecated LoggerSilence constant.

    Rafael Mendonça França

  • Remove deprecated fallback to I18n.default_local when config.i18n.fallbacks is empty.

    Rafael Mendonça França

  • Remove entries from local cache on RedisCacheStore#delete_matched

    Fixes #​38627

    ojab

  • Speed up ActiveSupport::SecurityUtils.fixed_length_secure_compare by using OpenSSL.fixed_length_secure_compare, if available.

    Nate Matykiewicz

  • ActiveSupport::Cache::MemCacheStore now checks ENV["MEMCACHE_SERVERS"] before falling back to "localhost:11211" if configured without any addresses.

    config.cache_store = :mem_cache_store

is now equivalent to

config.cache_store = :mem_cache_store, ENV["MEMCACHE_SERVERS"] || "localhost:11211"

instead of

config.cache_store = :mem_cache_store, "localhost:11211" # ignores ENV["MEMCACHE_SERVERS"]
```

*Sam Bostock*
  • ActiveSupport::Subscriber#attach_to now accepts an inherit_all: argument. When set to true, it allows a subscriber to receive events for methods defined in the subscriber's ancestor class(es).

    class ActionControllerSubscriber < ActiveSupport::Subscriber
      attach_to :action_controller
    
      def start_processing(event)
        info "Processing by #{event.payload[:controller]}##{event.payload[:action]} as #{format}"
      end
    
      def redirect_to(event)
        info { "Redirected to #{event.payload[:location]}" }
      end
    end

We detach ActionControllerSubscriber from the :action_controller namespace so that our CustomActionControllerSubscriber

can provide its own instrumentation for certain events in the namespace

ActionControllerSubscriber.detach_from(:action_controller)

class CustomActionControllerSubscriber < ActionControllerSubscriber
  attach_to :action_controller, inherit_all: true

  def start_processing(event)
    info "A custom response to start_processing events"
  end

=> CustomActionControllerSubscriber will process events for "start_processing.action_controller" notifications

using its own #start_processing implementation, while retaining ActionControllerSubscriber's instrumentation

for "redirect_to.action_controller" notifications

end
```

*Adrianna Chang*
  • Allow the digest class used to generate non-sensitive digests to be configured with config.active_support.hash_digest_class.

    config.active_support.use_sha1_digests is deprecated in favour of config.active_support.hash_digest_class = ::Digest::SHA1.

    Dirkjan Bussink

  • Fix bug to make memcached write_entry expire correctly with unless_exist

    Jye Lee

  • Add ActiveSupport::Duration conversion methods

    in_seconds, in_minutes, in_hours, in_days, in_weeks, in_months, and in_years return the respective duration covered.

    Jason York

  • Fixed issue in ActiveSupport::Cache::RedisCacheStore not passing options to read_multi causing fetch_multi to not work properly

    Rajesh Sharma

  • Fixed issue in ActiveSupport::Cache::MemCacheStore which caused duplicate compression, and caused the provided compression_threshold to not be respected.

    Max Gurewitz

  • Prevent RedisCacheStore and MemCacheStore from performing compression when reading entries written with raw: true.

    Max Gurewitz

  • URI.parser is deprecated and will be removed in Rails 6.2. Use URI::DEFAULT_PARSER instead.

    Jean Boussier

  • require_dependency has been documented to be obsolete in :zeitwerk mode. The method is not deprecated as such (yet), but applications are encouraged to not use it.

    In :zeitwerk mode, semantics match Ruby's and you do not need to be defensive with load order. Just refer to classes and modules normally. If the constant name is dynamic, camelize if needed, and constantize.

    Xavier Noria

  • Add 3rd person aliases of Symbol#start_with? and Symbol#end_with?.

    :foo.starts_with?("f") # => true
    :foo.ends_with?("o")   # => true

    Ryuta Kamizono

  • Add override of unary plus for ActiveSupport::Duration.

    + 1.second is now identical to +1.second to prevent errors where a seemingly innocent change of formatting leads to a change in the code behavior.

    Before:

    +1.second.class

=> ActiveSupport::Duration

(+ 1.second).class

=> Integer

```

After:
```ruby
+1.second.class

=> ActiveSupport::Duration

(+ 1.second).class

=> ActiveSupport::Duration

```

Fixes #&#8203;39079.

*Roman Kushnir*
  • Add subsec to ActiveSupport::TimeWithZone#inspect.

    Before:

    Time.at(1498099140).in_time_zone.inspect

=> "Thu, 22 Jun 2017 02:39:00 UTC +00:00"

    Time.at(1498099140, 123456780, :nsec).in_time_zone.inspect

=> "Thu, 22 Jun 2017 02:39:00 UTC +00:00"

    Time.at(1498099140 + Rational("1/3")).in_time_zone.inspect

=> "Thu, 22 Jun 2017 02:39:00 UTC +00:00"

After:

    Time.at(1498099140).in_time_zone.inspect

=> "Thu, 22 Jun 2017 02:39:00.000000000 UTC +00:00"

    Time.at(1498099140, 123456780, :nsec).in_time_zone.inspect

=> "Thu, 22 Jun 2017 02:39:00.123456780 UTC +00:00"

    Time.at(1498099140 + Rational("1/3")).in_time_zone.inspect

=> "Thu, 22 Jun 2017 02:39:00.333333333 UTC +00:00"

*akinomaeni*
  • Calling ActiveSupport::TaggedLogging#tagged without a block now returns a tagged logger.

    logger.tagged("BCX").info("Funky time!") # => [BCX] Funky time!

    Eugene Kenny

  • Align Range#cover? extension behavior with Ruby behavior for backwards ranges.

    (1..10).cover?(5..3) now returns false, as it does in plain Ruby.

    Also update #include? and #=== behavior to match.

    Michael Groeneman

  • Update to TZInfo v2.0.0.

    This changes the output of ActiveSupport::TimeZone.utc_to_local, but can be controlled with the ActiveSupport.utc_to_local_returns_utc_offset_times config.

    New Rails 6.1 apps have it enabled by default, existing apps can upgrade via the config in config/initializers/new_framework_defaults_6_1.rb

    See the utc_to_local_returns_utc_offset_times documentation for details.

    Phil Ross, Jared Beck

  • Add Date and Time #yesterday? and #tomorrow? alongside #today?.

    Aliased to #prev_day? and #next_day? to match the existing #prev/next_day methods.

    Jatin Dhankhar

  • Add Enumerable#pick to complement ActiveRecord::Relation#pick.

    Eugene Kenny

  • [Breaking change] ActiveSupport::Callbacks#halted_callback_hook now receive a 2nd argument:

    ActiveSupport::Callbacks#halted_callback_hook now receive the name of the callback being halted as second argument. This change will allow you to differentiate which callbacks halted the chain and act accordingly.

      class Book < ApplicationRecord
        before_save { throw(:abort) }
        before_create { throw(:abort) }
    
        def halted_callback_hook(filter, callback_name)
          Rails.logger.info("Book couldn't be #{callback_name}d")
        end
    
        Book.create # => "Book couldn't be created"
        book.save # => "Book couldn't be saved"
      end

    Edouard Chin

  • Support prepend with ActiveSupport::Concern.

    Allows a module with extend ActiveSupport::Concern to be prepended.

    module Imposter
      extend ActiveSupport::Concern

Same as included, except only run when prepended.

      prepended do
      end
    end

    class Person
      prepend Imposter
    end

Class methods are prepended to the base class, concerning is also
updated: `concerning :Imposter, prepend: true do`.

*Jason Karns*, *Elia Schito*
  • Deprecate using Range#include? method to check the inclusion of a value in a date time range. It is recommended to use Range#cover? method instead of Range#include? to check the inclusion of a value in a date time range.

    Vishal Telangre

  • Support added for a round_mode parameter, in all number helpers. (See: BigDecimal::mode.)

    number_to_currency(1234567890.50, precision: 0, round_mode: :half_down) # => "$1,234,567,890"
    number_to_percentage(302.24398923423, precision: 5, round_mode: :down) # => "302.24398%"
    number_to_rounded(389.32314, precision: 0, round_mode: :ceil) # => "390"
    number_to_human_size(483989, precision: 2, round_mode: :up) # => "480 KB"
    number_to_human(489939, precision: 2, round_mode: :floor) # => "480 Thousand"
    
    485000.to_s(:human, precision: 2, round_mode: :half_even) # => "480 Thousand"

    Tom Lord

  • Array#to_sentence no longer returns a frozen string.

    Before:

    ['one', 'two'].to_sentence.frozen?

=> true

After:

    ['one', 'two'].to_sentence.frozen?

=> false

*Nicolas Dular*
  • When an instance of ActiveSupport::Duration is converted to an iso8601 duration string, if weeks are mixed with date parts, the week part will be converted to days. This keeps the parser and serializer on the same page.

    duration = ActiveSupport::Duration.build(1000000)

1 week, 4 days, 13 hours, 46 minutes, and 40.0 seconds

duration_iso = duration.iso8601

P11DT13H46M40S

ActiveSupport::Duration.parse(duration_iso)

11 days, 13 hours, 46 minutes, and 40 seconds

duration = ActiveSupport::Duration.build(604800)

1 week

duration_iso = duration.iso8601

P1W

ActiveSupport::Duration.parse(duration_iso)

1 week

```

*Abhishek Sarkar*
  • Add block support to ActiveSupport::Testing::TimeHelpers#travel_back.

    Tim Masliuchenko

  • Update ActiveSupport::Messages::Metadata#fresh? to work for cookies with expiry set when ActiveSupport.parse_json_times = true.

    Christian Gregg

  • Support symbolic links for content_path in ActiveSupport::EncryptedFile.

    Takumi Shotoku

  • Improve Range#===, Range#include?, and Range#cover? to work with beginless (startless) and endless range targets.

    Allen Hsu, Andrew Hodgkinson

  • Don't use Process#clock_gettime(CLOCK_THREAD_CPUTIME_ID) on Solaris.

    Iain Beeston

  • Prevent ActiveSupport::Duration.build(value) from creating instances of ActiveSupport::Duration unless value is of type Numeric.

    Addresses the errant set of behaviours described in #​37012 where ActiveSupport::Duration comparisons would fail confusingly or return unexpected results when comparing durations built from instances of String.

    Before:

    small_duration_from_string = ActiveSupport::Duration.build('9')
    large_duration_from_string = ActiveSupport::Duration.build('100000000000000')
    small_duration_from_int = ActiveSupport::Duration.build(9)
    
    large_duration_from_string > small_duration_from_string

=> false

    small_duration_from_string == small_duration_from_int

=> false

    small_duration_from_int < large_duration_from_string

=> ArgumentError (comparison of ActiveSupport::Duration::Scalar with ActiveSupport::Duration failed)

    large_duration_from_string > small_duration_from_int

=> ArgumentError (comparison of String with ActiveSupport::Duration failed)

After:

    small_duration_from_string = ActiveSupport::Duration.build('9')

=> TypeError (can't build an ActiveSupport::Duration from a String)

*Alexei Emam*
  • Add ActiveSupport::Cache::Store#delete_multi method to delete multiple keys from the cache store.

    Peter Zhu

  • Support multiple arguments in HashWithIndifferentAccess for merge and update methods, to follow Ruby 2.6 addition.

    Wojciech Wnętrzak

  • Allow initializing thread_mattr_* attributes via :default option.

    class Scraper
      thread_mattr_reader :client, default: Api::Client.new
    end

    Guilherme Mansur

  • Add compact_blank for those times when you want to remove #blank? values from an Enumerable (also compact_blank! on Hash, Array, ActionController::Parameters).

    Dana Sherson

  • Make ActiveSupport::Logger Fiber-safe.

    Use Fiber.current.__id__ in ActiveSupport::Logger#local_level= in order to make log level local to Ruby Fibers in addition to Threads.

    Example:

    logger = ActiveSupport::Logger.new(STDOUT)
    logger.level = 1
    puts "Main is debug? #{logger.debug?}"
    
    Fiber.new {
      logger.local_level = 0
      puts "Thread is debug? #{logger.debug?}"
    }.resume
    
    puts "Main is debug? #{logger.debug?}"

    Before:

    Main is debug? false
    Thread is debug? true
    Main is debug? true

    After:

    Main is debug? false
    Thread is debug? true
    Main is debug? false

    Fixes #​36752.

    Alexander Varnin

  • Allow the on_rotation proc used when decrypting/verifying a message to be passed at the constructor level.

    Before:

    crypt = ActiveSupport::MessageEncryptor.new('long_secret')
    crypt.decrypt_and_verify(encrypted_message, on_rotation: proc { ... })
    crypt.decrypt_and_verify(another_encrypted_message, on_rotation: proc { ... })

    After:

    crypt = ActiveSupport::MessageEncryptor.new('long_secret', on_rotation: proc { ... })
    crypt.decrypt_and_verify(encrypted_message)
    crypt.decrypt_and_verify(another_encrypted_message)

    Edouard Chin

  • delegate_missing_to would raise a DelegationError if the object delegated to was nil. Now the allow_nil option has been added to enable the user to specify they want nil returned in this case.

    Matthew Tanous

  • truncate would return the original string if it was too short to be truncated and a frozen string if it were long enough to be truncated. Now truncate will consistently return an unfrozen string regardless. This behavior is consistent with gsub and strip.

    Before:

    'foobar'.truncate(5).frozen?

=> true

    'foobar'.truncate(6).frozen?

=> false

After:

    'foobar'.truncate(5).frozen?

=> false

    'foobar'.truncate(6).frozen?

=> false

*Jordan Thomas*

Active Model

  • Pass in base instead of base_class to Error.human_attribute_name

    This is useful in cases where the human_attribute_name method depends on other attributes' values of the class under validation to derive what the attribute name should be.

    Filipe Sabella

  • Deprecate marshalling load from legacy attributes format.

    Ryuta Kamizono

  • *_previously_changed? accepts :from and :to keyword arguments like *_changed?.

    topic.update!(status: :archived)
    topic.status_previously_changed?(from: "active", to: "archived")

=> true

*George Claghorn*
  • Raise FrozenError when trying to write attributes that aren't backed by the database on an object that is frozen:

    class Animal
      include ActiveModel::Attributes
      attribute :age
    end
    
    animal = Animal.new
    animal.freeze
    animal.age = 25 # => FrozenError, "can't modify a frozen Animal"

    Josh Brody

  • Add *_previously_was attribute methods when dirty tracking. Example:

    pirate.update(catchphrase: "Ahoy!")
    pirate.previous_changes["catchphrase"] # => ["Thar She Blows!", "Ahoy!"]
    pirate.catchphrase_previously_was # => "Thar She Blows!"

    DHH

  • Encapsulate each validation error as an Error object.

    The ActiveModel’s errors collection is now an array of these Error objects, instead of messages/details hash.

    For each of these Error object, its message and full_message methods are for generating error messages. Its details method would return error’s extra parameters, found in the original details hash.

    The change tries its best at maintaining backward compatibility, however some edge cases won’t be covered, like errors#first will return ActiveModel::Error and manipulating errors.messages and errors.details hashes directly will have no effect. Moving forward, please convert those direct manipulations to use provided API methods instead.

    The list of deprecated methods and their planned future behavioral changes at the next major release are:

    • errors#slice! will be removed.
    • errors#each with the key, value two-arguments block will stop working, while the error single-argument block would return Error object.
    • errors#values will be removed.
    • errors#keys will be removed.
    • errors#to_xml will be removed.
    • errors#to_h will be removed, and can be replaced with errors#to_hash.
    • Manipulating errors itself as a hash will have no effect (e.g. errors[:foo] = 'bar').
    • Manipulating the hash returned by errors#messages (e.g. errors.messages[:foo] = 'bar') will have no effect.
    • Manipulating the hash returned by errors#details (e.g. errors.details[:foo].clear) will have no effect.

    lulalala

Active Record

  • Only warn about negative enums if a positive form that would cause conflicts exists.

    Fixes #​39065.

    Alex Ghiculescu

  • Change attribute_for_inspect to take filter_attributes in consideration.

    Rafael Mendonça França

  • Fix odd behavior of inverse_of with multiple belongs_to to same class.

    Fixes #​35204.

    Tomoyuki Kai

  • Build predicate conditions with objects that delegate #id and primary key:

    class AdminAuthor
      delegate_missing_to :@&#8203;author
    
      def initialize(author)
        @&#8203;author = author
      end
    end
    
    Post.where(author: AdminAuthor.new(author))

    Sean Doyle

  • Add connected_to_many API.

    This API allows applications to connect to multiple databases at once without switching all of them or implementing a deeply nested stack.

    Before:

    AnimalsRecord.connected_to(role: :reading) do MealsRecord.connected_to(role: :reading) do Dog.first # read from animals replica Dinner.first # read from meals replica Person.first # read from primary writer end end

    After:

    ActiveRecord::Base.connected_to_many([AnimalsRecord, MealsRecord], role: :reading) do Dog.first # read from animals replica Dinner.first # read from meals replica Person.first # read from primary writer end

    Eileen M. Uchitelle, John Crepezzi

  • Add option to raise or log for ActiveRecord::StrictLoadingViolationError.

    Some applications may not want to raise an error in production if using strict_loading. This would allow an application to set strict loading to log for the production environment while still raising in development and test environments.

    Set config.active_record.action_on_strict_loading_violation to :log errors instead of raising.

    Eileen M. Uchitelle

  • Allow the inverse of a has_one association that was previously autosaved to be loaded.

    Fixes #​34255.

    Steven Weber

  • Optimise the length of index names for polymorphic references by using the reference name rather than the type and id column names.

    Because the default behaviour when adding an index with multiple columns is to use all column names in the index name, this could frequently lead to overly long index names for polymorphic references which would fail the migration if it exceeded the database limit.

    This change reduces the chance of that happening by using the reference name, e.g. index_my_table_on_my_reference.

    Fixes #​38655.

    Luke Redpath

  • MySQL: Uniqueness validator now respects default database collation, no longer enforce case sensitive comparison by default.

    Ryuta Kamizono

  • Remove deprecated methods from ActiveRecord::ConnectionAdapters::DatabaseLimits.

    column_name_length table_name_length columns_per_table indexes_per_table columns_per_multicolumn_index sql_query_length joins_per_query

    Rafael Mendonça França

  • Remove deprecated ActiveRecord::ConnectionAdapters::AbstractAdapter#supports_multi_insert?.

    Rafael Mendonça França

  • Remove deprecated ActiveRecord::ConnectionAdapters::AbstractAdapter#supports_foreign_keys_in_create?.

    Rafael Mendonça França

  • Remove deprecated ActiveRecord::ConnectionAdapters::PostgreSQLAdapter#supports_ranges?.

    Rafael Mendonça França

  • Remove deprecated ActiveRecord::Base#update_attributes and ActiveRecord::Base#update_attributes!.

    Rafael Mendonça França

  • Remove deprecated migrations_path argument in ActiveRecord::ConnectionAdapter::SchemaStatements#assume_migrated_upto_version.

    Rafael Mendonça França

  • Remove deprecated config.active_record.sqlite3.represent_boolean_as_integer.

    Rafael Mendonça França

  • relation.create does no longer leak scope to class level querying methods in initialization block and callbacks.

    Before:

    User.where(name: "John").create do |john|
      User.find_by(name: "David") # => nil
    end

    After:

    User.where(name: "John").create do |john|
      User.find_by(name: "David") # => #<User name: "David", ...>
    end

    Ryuta Kamizono

  • Named scope chain does no longer leak scope to class level querying methods.

    class User < ActiveRecord::Base
      scope :david, -> { User.where(name: "David") }
    end

    Before:

    User.where(name: "John").david

SELECT * FROM users WHERE name = 'John' AND name = 'David'

After:

    User.where(name: "John").david

SELECT * FROM users WHERE name = 'David'

*Ryuta Kamizono*
  • Remove deprecated methods from ActiveRecord::DatabaseConfigurations.

    fetch each first values []=

    Rafael Mendonça França

  • where.not now generates NAND predicates instead of NOR.

    Before:

     User.where.not(name: "Jon", role: "admin")

SELECT * FROM users WHERE name != 'Jon' AND role != 'admin'

 After:

     User.where.not(name: "Jon", role: "admin")

SELECT * FROM users WHERE NOT (name == 'Jon' AND role == 'admin')

*Rafael Mendonça França*
  • Remove deprecated ActiveRecord::Result#to_hash method.

    Rafael Mendonça França

  • Deprecate ActiveRecord::Base.allow_unsafe_raw_sql.

    Rafael Mendonça França

  • Remove deprecated support for using unsafe raw SQL in ActiveRecord::Relation methods.

    Rafael Mendonça França

  • Allow users to silence the "Rails couldn't infer whether you are using multiple databases..." message using config.active_record.suppress_multiple_database_warning.

    Omri Gabay

  • Connections can be granularly switched for abstract classes when connected_to is called.

    This change allows connected_to to switch a role and/or shard for a single abstract class instead of all classes globally. Applications that want to use the new feature need to set config.active_record.legacy_connection_handling to false in their application configuration.

    Example usage:

    Given an application we have a User model that inherits from ApplicationRecord and a Dog model that inherits from AnimalsRecord. AnimalsRecord and ApplicationRecord have writing and reading connections as well as shard default, one, and two.

    ActiveRecord::Base.connected_to(role: :reading) do
      User.first # reads from default replica
      Dog.first # reads from default replica
    
      AnimalsRecord.connected_to(role: :writing, shard: :one) do
        User.first # reads from default replica
        Dog.first # reads from shard one primary
      end
    
      User.first # reads from default replica
      Dog.first # reads from default replica
    
      ApplicationRecord.connected_to(role: :writing, shard: :two) do
        User.first # reads from shard two primary
        Dog.first # reads from default replica
      end
    end

    Eileen M. Uchitelle, John Crepezzi

  • Allow double-dash comment syntax when querying read-only databases

    James Adam

  • Add values_at method.

    Returns an array containing the values associated with the given methods.

    topic = Topic.first
    topic.values_at(:title, :author_name)

=> ["Budget", "Jason"]

```

Similar to `Hash#values_at` but on an Active Record instance.

*Guillaume Briday*
  • Fix read_attribute_before_type_cast to consider attribute aliases.

    Marcelo Lauxen

  • Support passing record to uniqueness validator :conditions callable:

    class Article < ApplicationRecord
      validates_uniqueness_of :title, conditions: ->(article) {
        published_at = article.published_at
        where(published_at: published_at.beginning_of_year..published_at.end_of_year)
      }
    end

    Eliot Sykes

  • BatchEnumerator#update_all and BatchEnumerator#delete_all now return the total number of rows affected, just like their non-batched counterparts.

    Person.in_batches.update_all("first_name = 'Eugene'") # => 42
    Person.in_batches.delete_all # => 42

    Fixes #​40287.

    Eugene Kenny

  • Add support for PostgreSQL interval data type with conversion to ActiveSupport::Duration when loading records from database and serialization to ISO 8601 formatted duration string on save. Add support to define a column in migrations and get it in a schema dump. Optional column precision is supported.

    To use this in 6.1, you need to place the next string to your model file:

    attribute :duration, :interval

    To keep old behavior until 6.2 is released:

    attribute :duration, :string

    Example:

    create_table :events do |t|
      t.string   :name
      t.interval :duration
    end
    
    class Event < ApplicationRecord
      attribute :duration, :interval
    end
    
    Event.create!(name: 'Rock Fest', duration: 2.days)
    Event.last.duration # => 2 days
    Event.last.duration.iso8601 # => "P2D"
    Event.new(duration: 'P1DT12H3S').duration # => 1 day, 12 hours, and 3 seconds
    Event.new(duration: '1 day') # Unknown value will be ignored and NULL will be written to database

    Andrey Novikov

  • Allow associations supporting the dependent: key to take dependent: :destroy_async.

    class Account < ActiveRecord::Base
        belongs_to :supplier, dependent: :destroy_async
    end

    :destroy_async will enqueue a job to destroy associated records in the background.

    DHH, George Claghorn, Cory Gwin, Rafael Mendonça França, Adrianna Chang

  • Add SKIP_TEST_DATABASE environment variable to disable modifying the test database when rails db:create and rails db:drop are called.

    Jason Schweier

  • connects_to can only be called on ActiveRecord::Base or abstract classes.

    Ensure that connects_to can only be called from ActiveRecord::Base or abstract classes. This protects the application from opening duplicate or too many connections.

    Eileen M. Uchitelle, John Crepezzi

  • All connection adapters execute now raises ActiveRecord::ConnectionNotEstablished rather than ActiveRecord::StatementInvalid when they encounter a connection error.

    Jean Boussier

  • Mysql2Adapter#quote_string now raises ActiveRecord::ConnectionNotEstablished rather than ActiveRecord::StatementInvalid when it can't connect to the MySQL server.

    Jean Boussier

  • Add support for check constraints that are NOT VALID via validate: false (PostgreSQL-only).

    Alex Robbin

  • Ensure the default configuration is considered primary or first for an environment

    If a multiple database application provides a configuration named primary, that will be treated as default. In applications that do not have a primary entry, the default database configuration will be the first configuration for an environment.

    Eileen M. Uchitelle

  • Allow where references association names as joined table name aliases.

    class Comment < ActiveRecord::Base
      enum label: [:default, :child]
      has_many :children, class_name: "Comment", foreign_key: :parent_id
    end

... FROM comments LEFT OUTER JOIN comments children ON ... WHERE children.label = 1

Comment.includes(:children).where("children.label": "child")
```

*Ryuta Kamizono*
  • Support storing demodulized class name for polymorphic type.

    Before Rails 6.1, storing demodulized class name is supported only for STI type by store_full_sti_class class attribute.

    Now store_full_class_name class attribute can handle both STI and polymorphic types.

    Ryuta Kamizono

  • Deprecate rails db:structure:{load, dump} tasks and extend rails db:schema:{load, dump} tasks to work with either :ruby or :sql format, depending on config.active_record.schema_format configuration value.

    fatkodima

  • Respect the select values for eager loading.

    post = Post.select("UPPER(title) AS title").first
    post.title # => "WELCOME TO THE WEBLOG"
    post.body  # => ActiveModel::MissingAttributeError

Rails 6.0 (ignore the select values)

post = Post.select("UPPER(title) AS title").eager_load(:comments).first
post.title # => "Welcome to the weblog"
post.body  # => "Such a lovely day"

Rails 6.1 (respect the select values)

post = Post.select("UPPER(title) AS title").eager_load(:comments).first
post.title # => "WELCOME TO THE WEBLOG"
post.body  # => ActiveModel::MissingAttributeError
```

*Ryuta Kamizono*
  • Allow attribute's default to be configured but keeping its own type.

    class Post < ActiveRecord::Base
      attribute :written_at, default: -> { Time.now.utc }
    end

Rails 6.0

Post.type_for_attribute(:written_at) # => #<Type::Value ... precision: nil, ...>

Rails 6.1

Post.type_for_attribute(:written_at) # => #<Type::DateTime ... precision: 6, ...>
```

*Ryuta Kamizono*
  • Allow default to be configured for Enum.

    class Book < ActiveRecord::Base
      enum status: [:proposed, :written, :published], _default: :published
    end
    
    Book.new.status # => "published"

    Ryuta Kamizono

  • Deprecate YAML loading from legacy format older than Rails 5.0.

    Ryuta Kamizono

  • Added the setting ActiveRecord::Base.immutable_strings_by_default, which allows you to specify that all string columns should be frozen unless otherwise specified. This will reduce memory pressure for applications which do not generally mutate string properties of Active Record objects.

    Sean Griffin, Ryuta Kamizono

  • Deprecate map! and collect! on ActiveRecord::Result.

    Ryuta Kamizono

  • Support relation.and for intersection as Set theory.

    david_and_mary = Author.where(id: [david, mary])
    mary_and_bob   = Author.where(id: [mary, bob])
    
    david_and_mary.merge(mary_and_bob) # => [mary, bob]
    
    david_and_mary.and(mary_and_bob) # => [mary]
    david_and_mary.or(mary_and_bob)  # => [david, mary, bob]

    Ryuta Kamizono

  • Merging conditions on the same column no longer maintain both conditions, and will be consistently replaced by the latter condition in Rails 6.2. To migrate to Rails 6.2's behavior, use relation.merge(other, rewhere: true).

Rails 6.1 (IN clause is replaced by merger side equality condition)

Author.where(id: [david.id, mary.id]).merge(Author.where(id: bob)) # => [bob]

Rails 6.1 (both conflict conditions exists, deprecated)

Author.where(id: david.id..mary.id).merge(Author.where(id: bob)) # => []

Rails 6.1 with rewhere to migrate to Rails 6.2's behavior

Author.where(id: david.id..mary.id).merge(Author.where(id: bob), rewhere: true) # => [bob]

Rails 6.2 (same behavior with IN clause, mergee side condition is consistently replaced)

Author.where(id: [david.id, mary.id]).merge(Author.where(id: bob)) # => [bob]
Author.where(id: david.id..mary.id).merge(Author.where(id: bob)) # => [bob]
```

*Ryuta Kamizono*
  • Do not mark Postgresql MAC address and UUID attributes as changed when the assigned value only varies by case.

    Peter Fry

  • Resolve issue with insert_all unique_by option when used with expression index.

    When the :unique_by option of ActiveRecord::Persistence.insert_all and ActiveRecord::Persistence.upsert_all was used with the name of an expression index, an error was raised. Adding a guard around the formatting behavior for the :unique_by corrects this.

    Usage:

    create_table :books, id: :integer, force: true do |t|
      t.column :name, :string
      t.index "lower(name)", unique: true
    end
    
    Book.insert_all [{ name: "MyTest" }], unique_by: :index_books_on_lower_name

    Fixes #​39516.

    Austen Madden

  • Add basic support for CHECK constraints to database migrations.

    Usage:

    add_check_constraint :products, "price > 0", name: "price_check"
    remove_check_constraint :products, name: "price_check"

    fatkodima

  • Add ActiveRecord::Base.strict_loading_by_default and ActiveRecord::Base.strict_loading_by_default= to enable/disable strict_loading mode by default for a model. The configuration's value is inheritable by subclasses, but they can override that value and it will not impact parent class.

    Usage:

    class Developer < ApplicationRecord
      self.strict_loading_by_default = true
    
      has_many :projects
    end
    
    dev = Developer.first
    dev.projects.first

=> ActiveRecord::StrictLoadingViolationError Exception: Developer is marked as strict_loading and Project cannot be lazily loaded.

```

*bogdanvlviv*
  • Deprecate passing an Active Record object to quote/type_cast directly.

    Ryuta Kamizono

  • Default engine ENGINE=InnoDB is no longer dumped to make schema more agnostic.

    Before:

    create_table "accounts", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci", force: :cascade do |t|
    end

    After:

    create_table "accounts", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
    end

    Ryuta Kamizono

  • Added delegated type as an alternative to single-table inheritance for representing class hierarchies. See ActiveRecord::DelegatedType for the full description.

    DHH

  • Deprecate aggregations with group by duplicated fields.

    To migrate to Rails 6.2's behavior, use uniq!(:group) to deduplicate group fields.

    accounts = Account.group(:firm_id)

duplicated group fields, deprecated.

accounts.merge(accounts.where.not(credit_limit: nil)).sum(:credit_limit)

=> {

[1, 1] => 50,

[2, 2] => 60

}

use uniq!(:group) to deduplicate group fields.

accounts.merge(accounts.where.not(credit_limit: nil)).uniq!(:group).sum(:credit_limit)

=> {

1 => 50,

2 => 60

}

```

*Ryuta Kamizono*
  • Deprecate duplicated query annotations.

    To migrate to Rails 6.2's behavior, use uniq!(:annotate) to deduplicate query annotations.

    accounts = Account.where(id: [1, 2]).annotate("david and mary")

duplicated annotations, deprecated.

accounts.merge(accounts.rewhere(id: 3))

SELECT accounts.* FROM accounts WHERE accounts.id = 3 /* david and mary / / david and mary */

use uniq!(:annotate) to deduplicate annotations.

accounts.merge(accounts.rewhere(id: 3)).uniq!(:annotate)

SELECT accounts.* FROM accounts WHERE accounts.id = 3 /* david and mary */

```

*Ryuta Kamizono*
  • Resolve conflict between counter cache and optimistic locking.

    Bump an Active Record instance's lock version after updating its counter cache. This avoids raising an unnecessary ActiveRecord::StaleObjectError upon subsequent transactions by maintaining parity with the corresponding database record's lock_version column.

    Fixes #​16449.

    Aaron Lipman

  • Support merging option :rewhere to allow mergee side condition to be replaced exactly.

    david_and_mary = Author.where(id: david.id..mary.id)

both conflict conditions exists

david_and_mary.merge(Author.where(id: bob)) # => []

mergee side condition is replaced by rewhere

david_and_mary.merge(Author.rewhere(id: bob)) # => [bob]

mergee side condition is replaced by rewhere option

david_and_mary.merge(Author.where(id: bob), rewhere: true) # => [bob]
```

*Ryuta Kamizono*
  • Add support for finding records based on signed ids, which are tamper-proof, verified ids that can be set to expire and scoped with a purpose. This is particularly useful for things like password reset or email verification, where you want the bearer of the signed id to be able to interact with the underlying record, but usually only within a certain time period.

    signed_id = User.first.signed_id expires_in: 15.minutes, purpose: :password_reset
    
    User.find_signed signed_id # => nil, since the purpose does not match
    
    travel 16.minutes
    User.find_signed signed_id, purpose: :password_reset # => nil, since the signed id has expired
    
    travel_back
    User.find_signed signed_id, purpose: :password_reset # => User.first
    
    User.find_signed! "bad data" # => ActiveSupport::MessageVerifier::InvalidSignature

    DHH

  • Support ALGORITHM = INSTANT DDL option for index operations on MySQL.

    Ryuta Kamizono

  • Fix index creation to preserve index comment in bulk change table on MySQL.

    Ryuta Kamizono

  • Allow unscope to be aware of table name qualified values.

    It is possible to unscope only the column in the specified table.

    posts = Post.joins(:comments).group(:"posts.hidden")
    posts = posts.where("posts.hidden": false, "comments.hidden": false)
    
    posts.count

=> { false => 10 }

unscope both hidden columns

posts.unscope(where: :hidden).count

=> { false => 11, true => 1 }

unscope only comments.hidden column

posts.unscope(where: :"comments.hidden").count

=> { false => 11 }

```

*Ryuta Kamizono*, *Slava Korolev*
  • Fix rewhere to truly overwrite collided where clause by new where clause.

    steve = Person.find_by(name: "Steve")
    david = Author.find_by(name: "David")
    
    relation = Essay.where(writer: steve)

Before

relation.rewhere(writer: david).to_a # => []

After

relation.rewhere(writer: david).to_a # => [david]
```

*Ryuta Kamizono*
  • Inspect time attributes with subsec and time zone offset.

    p Knot.create
    => #<Knot id: 1, created_at: "2016-05-05 01:29:47.116928000 +0000">

    akinomaeni, Jonathan Hefner

  • Deprecate passing a column to type_cast.

    Ryuta Kamizono

  • Deprecate in_clause_length and allowed_index_name_length in DatabaseLimits.

    Ryuta Kamizono

  • Support bulk insert/upsert on relation to preserve scope values.

    Josef Šimánek, Ryuta Kamizono

  • Preserve column comment value on changing column name on MySQL.

    Islam Taha

  • Add support for if_exists option for removing an index.

    The remove_index method can take an if_exists option. If this is set to true an error won't be raised if the index doesn't exist.

    Eileen M. Uchitelle

  • Remove ibm_db, informix, mssql, oracle, and oracle12 Arel visitors which are not used in the code base.

    Ryuta Kamizono

  • Prevent build_association from touching a parent record if the record isn't persisted for has_one associations.

    Fixes #​38219.

    Josh Brody

  • Add support for if_not_exists option for adding index.

    The add_index method respects if_not_exists option. If it is set to true index won't be added.

    Usage:

      add_index :users, :account_id, if_not_exists: true

    The if_not_exists option passed to create_table also gets propagated to indexes created within that migration so that if table and its indexes exist then there is no attempt to create them again.

    Prathamesh Sonpatki

  • Add ActiveRecord::Base#previously_new_record? to show if a record was new before the last save.

    Tom Ward

  • Support descending order for find_each, find_in_batches, and in_batches.

    Batch processing methods allow you to work with the records in batches, greatly reducing memory consumption, but records are always batched from oldest id to newest.

    This change allows reversing the order, batching from newest to oldest. This is useful when you need to process newer batches of records first.

    Pass order: :desc to yield batches in descending order. The default remains order: :asc.

    Person.find_each(order: :desc) do |person|
      person.party_all_night!
    end

    Alexey Vasiliev

  • Fix insert_all with enum values.

    Fixes #​38716.

    Joel Blum

  • Add support for db:rollback:name for multiple database applications.

    Multiple database applications will now raise if db:rollback is call and recommend using the db:rollback:[NAME] to rollback migrations.

    Eileen M. Uchitelle

  • Relation#pick now uses already loaded results instead of making another query.

    Eugene Kenny

  • Deprecate using return, break or throw to exit a transaction block after writes.

    Dylan Thacker-Smith

  • Dump the schema or structure of a database when calling db:migrate:name.

    In previous versions of Rails, rails db:migrate would dump the schema of the database. In Rails 6, that holds true (rails db:migrate dumps all databases' schemas), but rails db:migrate:name does not share that behavior.

    Going forward, calls to rails db:migrate:name will dump the schema (or structure) of the database being migrated.

    Kyle Thompson

  • Reset the ActiveRecord::Base connection after rails db:migrate:name.

    When rails db:migrate has finished, it ensures the ActiveRecord::Base connection is reset to its original configuration. Going forward, rails db:migrate:name will have the same behavior.

    Kyle Thompson

  • Disallow calling connected_to on subclasses of ActiveRecord::Base.

    Behavior has not changed here but the previous API could be misleading to people who thought it would switch connections for only that class. connected_to switches the context from which we are getting connections, not the connections themselves.

    Eileen M. Uchitelle, John Crepezzi

  • Add support for horizontal sharding to connects_to and connected_to.

    Applications can now connect to multiple shards and switch between their shards in an application. Note that the shard swapping is still a manual process as this change does not include an API for automatic shard swapping.

    Usage:

    Given the following configuration:

config/database.yml

production:
  primary:
    database: my_database
  primary_shard_one:
    database: my_database_shard_one
```

Connect to multiple shards:

```ruby
class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true

  connects_to shards: {
    default: { writing: :primary },
    shard_one: { writing: :primary_shard_one }
  }
```

Swap between shards in your controller / model code:

```ruby
ActiveRecord::Base.connected_to(shard: :shard_one) do

Read from shard one

end
```

The horizontal sharding API also supports read replicas. See guides for more details.

*Eileen M. Uchitelle*, *John Crepezzi*
  • Deprecate spec_name in favor of name on database configurations.

    The accessors for spec_name on configs_for and DatabaseConfig are deprecated. Please use name instead.

    Deprecated behavior:

    db_config = ActiveRecord::Base.configs_for(env_name: "development", spec_name: "primary")
    db_config.spec_name

    New behavior:

    db_config = ActiveRecord::Base.configs_for(env_name: "development", name: "primary")
    db_config.name

    Eileen M. Uchitelle

  • Add additional database-specific rake tasks for multi-database users.

    Previously, rails db:create, rails db:drop, and rails db:migrate were the only rails tasks that could operate on a single database. For example:

    rails db:create
    rails db:create:primary
    rails db:create:animals
    rails db:drop
    rails db:drop:primary
    rails db:drop:animals
    rails db:migrate
    rails db:migrate:primary
    rails db:migrate:animals

    With these changes, rails db:schema:dump, rails db:schema:load, rails db:structure:dump, rails db:structure:load and rails db:test:prepare can additionally operate on a single database. For example:

    rails db:schema:dump
    rails db:schema:dump:primary
    rails db:schema:dump:animals
    rails db:schema:load
    rails db:schema:load:primary
    rails db:schema:load:animals
    rails db:structure:dump
    rails db:structure:dump:primary
    rails db:structure:dump:animals
    rails db:structure:load
    rails db:structure:load:primary
    rails db:structure:load:animals
    rails db:test:prepare
    rails db:test:prepare:primary
    rails db:test:prepare:animals

    Kyle Thompson

  • Add support for strict_loading mode on association declarations.

    Raise an error if attempting to load a record from an association that has been marked as strict_loading unless it was explicitly eager loaded.

    Usage:

    class Developer < ApplicationRecord
      has_many :projects, strict_loading: true
    end
    
    dev = Developer.first
    dev.projects.first

=> ActiveRecord::StrictLoadingViolationError: The projects association is marked as strict_loading and cannot be lazily loaded.

```

*Kevin Deisz*
  • Add support for strict_loading mode to prevent lazy loading of records.

    Raise an error if a parent record is marked as strict_loading and attempts to lazily load its associations. This is useful for finding places you may want to preload an association and avoid additional queries.

    Usage:

    dev = Developer.strict_loading.first
    dev.audit_logs.to_a

=> ActiveRecord::StrictLoadingViolationError: Developer is marked as strict_loading and AuditLog cannot be lazily loaded.

```

*Eileen M. Uchitelle*, *Aaron Patterson*
  • Add support for PostgreSQL 11+ partitioned indexes when using upsert_all.

    Sebastián Palma

  • Adds support for if_not_exists to add_column and if_exists to remove_column.

    Applications can set their migrations to ignore exceptions raised when adding a column that already exists or when removing a column that does not exist.

    Example Usage:

    class AddColumnTitle < ActiveRecord::Migration[6.1]
      def change
        add_column :posts, :title, :string, if_not_exists: true
      end
    end
    class RemoveColumnTitle < ActiveRecord::Migration[6.1]
      def change
        remove_column :posts, :title, if_exists: true
      end
    end

    Eileen M. Uchitelle

  • Regexp-escape table name for MS SQL Server.

    Add Regexp.escape to one method in ActiveRecord, so that table names with regular expression characters in them work as expected. Since MS SQL Server uses "[" and "]" to quote table and column names, and those characters are regular expression characters, methods like pluck and select fail in certain cases when used with the MS SQL Server adapter.

    Larry Reid

  • Store advisory locks on their own named connection.

    Previously advisory locks were taken out against a connection when a migration started. This works fine in single database applications but doesn't work well when migrations need to open new connections which results in the lock getting dropped.

    In order to fix this we are storing the advisory lock on a new connection with the connection specification name AdvisoryLockBase. The caveat is that we need to maintain at least 2 connections to a database while migrations are running in order to do this.

    Eileen M. Uchitelle, John Crepezzi

  • Allow schema cache path to be defined in the database configuration file.

    For example:

    development:
      adapter: postgresql
      database: blog_development
      pool: 5
      schema_cache_path: tmp/schema/main.yml

    Katrina Owen

  • Deprecate #remove_connection in favor of #remove_connection_pool when called on the handler.

    #remove_connection is deprecated in order to support returning a DatabaseConfig object instead of a Hash. Use #remove_connection_pool, #remove_connection will be removed in 6.2.

    Eileen M. Uchitelle, John Crepezzi

  • Deprecate #default_hash and it's alias #[] on database configurations.

    Applications should use configs_for. #default_hash and #[] will be removed in 6.2.

    Eileen M. Uchitelle, John Crepezzi

  • Add scale support to ActiveRecord::Validations::NumericalityValidator.

    Gannon McGibbon

  • Find orphans by looking for missing relations through chaining where.missing:

    Before:

    Post.left_joins(:author).where(authors: { id: nil })

    After:

    Post.where.missing(:author)

    Tom Rossi

  • Ensure :reading connections always raise if a write is attempted.

    Now Rails will raise an ActiveRecord::ReadOnlyError if any connection on the reading handler attempts to make a write. If your reading role needs to write you should name the role something other than :reading.

    Eileen M. Uchitelle

  • Deprecate "primary" as the connection_specification_name for ActiveRecord::Base.

    "primary" has been deprecated as the connection_specification_name for ActiveRecord::Base in favor of using "ActiveRecord::Base". This change affects calls to ActiveRecord::Base.connection_handler.retrieve_connection and ActiveRecord::Base.connection_handler.remove_connection. If you're calling these methods with "primary", please switch to "ActiveRecord::Base".

    Eileen M. Uchitelle, John Crepezzi

  • Add ActiveRecord::Validations::NumericalityValidator with support for casting floats using a database columns' precision value.

    Gannon McGibbon

  • Enforce fresh ETag header after a collection's contents change by adding ActiveRecord::Relation#cache_key_with_version. This method will be used by ActionController::ConditionalGet to ensure that when collection cache versioning is enabled, requests using ConditionalGet don't return the same ETag header after a collection is modified.

    Fixes #​38078.

    Aaron Lipman

  • Skip test database when running db:create or db:drop in development with DATABASE_URL set.

    Brian Buchalter

  • Don't allow mutations on the database configurations hash.

    Freeze the configurations hash to disallow directly changing it. If applications need to change the hash, for example to create databases for parallelization, they should use the DatabaseConfig object directly.

    Before:

    @&#8203;db_config = ActiveRecord::Base.configurations.configs_for(env_name: "test", spec_name: "primary")
    @&#8203;db_config.configuration_hash.merge!(idle_timeout: "0.02")

    After:

    @&#8203;db_config = ActiveRecord::Base.configurations.configs_for(env_name: "test", spec_name: "primary")
    config = @&#8203;db_config.configuration_hash.merge(idle_timeout: "0.02")
    db_config = ActiveRecord::DatabaseConfigurations::HashConfig.new(@&#8203;db_config.env_name, @&#8203;db_config.spec_name, config)

    Eileen M. Uchitelle, John Crepezzi

  • Remove :connection_id from the sql.active_record notification.

    Aaron Patterson, Rafael Mendonça França

  • The :name key will no longer be returned as part of DatabaseConfig#configuration_hash. Please use DatabaseConfig#owner_name instead.

    Eileen M. Uchitelle, John Crepezzi

  • ActiveRecord's belongs_to_required_by_default flag can now be set per model.

    You can now opt-out/opt-in specific models from having their associations required by default.

    This change is meant to ease the process of migrating all your models to have their association required.

    Edouard Chin

  • The connection_config method has been deprecated, please use connection_db_config instead which will return a DatabaseConfigurations::DatabaseConfig instead of a Hash.

    Eileen M. Uchitelle, John Crepezzi

  • Retain explicit selections on the base model after applying includes and joins.

    Resolves #​34889.

    Patrick Rebsch

  • The database kwarg is deprecated without replacement because it can't be used for sharding and creates an issue if it's used during a request. Applications that need to create new connections should use connects_to instead.

    Eileen M. Uchitelle, John Crepezzi

  • Allow attributes to be fetched from Arel node groupings.

    Jeff Emminger, Gannon McGibbon

  • A database URL can now contain a querystring value that contains an equal sign. This is needed to support passing PostgreSQL options.

    Joshua Flanagan

  • Calling methods like establish_connection with a Hash which is invalid (eg: no adapter) will now raise an error the same way as connections defined in config/database.yml.

    John Crepezzi

  • Specifying implicit_order_column now subsorts the records by primary key if available to ensure deterministic results.

    Paweł Urbanek

  • where(attr => []) now loads an empty result without making a query.

    John Hawthorn

  • Fixed the performance regression for primary_keys introduced MySQL 8.0.

    Hiroyuki Ishii

  • Add support for belongs_to to has_many inversing.

    Gannon McGibbon

  • Allow length configuration for has_secure_token method. The minimum length is set at 24 characters.

    Before:

    has_secure_token :auth_token

    After:

    has_secure_token :default_token             # 24 characters
    has_secure_token :auth_token, length: 36    # 36 characters
    has_secure_token :invalid_token, length: 12 # => ActiveRecord::SecureToken::MinimumLengthError

    Bernardo de Araujo

  • Deprecate DatabaseConfigurations#to_h. These connection hashes are still available via ActiveRecord::Base.configurations.configs_for.

    Eileen Uchitelle, John Crepezzi

  • Add DatabaseConfig#configuration_hash to return database configuration hashes with symbol keys, and use all symbol-key configuration hashes internally. Deprecate DatabaseConfig#config which returns a String-keyed Hash with the same values.

    John Crepezzi, Eileen Uchitelle

  • Allow column names to be passed to remove_index positionally along with other options.

    Passing other options can be necessary to make remove_index correctly reversible.

    Before:

    add_index    :reports, :report_id               # => works
    add_index    :reports, :report_id, unique: true # => works
    remove_index :reports, :report_id               # => works
    remove_index :reports, :report_id, unique: true # => ArgumentError

    After:

    remove_index :reports, :report_id, unique: true # => works

    Eugene Kenny

  • Allow bulk ALTER statements to drop and recreate indexes with the same name.

    Eugene Kenny

  • insert, insert_all, upsert, and upsert_all now clear the query cache.

    Eugene Kenny

  • Call while_preventing_writes directly from connected_to.

    In some cases application authors want to use the database switching middleware and make explicit calls with connected_to. It's possible for an app to turn off writes and not turn them back on by the time we call connected_to(role: :writing).

    This change allows apps to fix this by assuming if a role is writing we want to allow writes, except in the case it's explicitly turned off.

    Eileen M. Uchitelle

  • Improve detection of ActiveRecord::StatementTimeout with mysql2 adapter in the edge case when the query is terminated during filesort.

    Kir Shatrov

  • Stop trying to read yaml file fixtures when loading Active Record fixtures.

    Gannon McGibbon

  • Deprecate .reorder(nil) with .first / .first! taking non-deterministic result.

    To continue taking non-deterministic result, use .take / .take! instead.

    Ryuta Kamizono

  • Preserve user supplied joins order as much as possible.

    Fixes #​36761, #​34328, #​24281, #​12953.

    Ryuta Kamizono

  • Allow matches_regex and does_not_match_regexp on the MySQL Arel visitor.

    James Pearson

  • Allow specifying fixtures to be ignored by setting ignore in YAML file's '_fixture' section.

    Tongfei Gao

  • Make the DATABASE_URL env variable only affect the primary connection. Add new env variables for multiple databases.

    John Crepezzi, Eileen Uchitelle

  • Add a warning for enum elements with 'not_' prefix.

    class Foo
      enum status: [:sent, :not_sent]
    end

    Edu Depetris

  • Make currency symbols optional for money column type in PostgreSQL.

    Joel Schneider

  • Add support for beginless ranges, introduced in Ruby 2.7.

    Josh Goodall

  • Add database_exists? method to connection adapters to check if a database exists.

    Guilherme Mansur

  • Loading the schema for a model that has no table_name raises a TableNotSpecified error.

    Guilherme Mansur, Eugene Kenny

  • PostgreSQL: Fix GROUP BY with ORDER BY virtual count attribute.

    Fixes #​36022.

    Ryuta Kamizono

  • Make ActiveRecord ConnectionPool.connections method thread-safe.

    Fixes #​36465.

    Jeff Doering

  • Add support for multiple databases to rails db:abort_if_pending_migrations.

    Mark Lee

  • Fix sqlite3 collation parsing when using decimal columns.

    Martin R. Schuster

  • Fix invalid schema when primary key column has a comment.

    Fixes #​29966.

    Guilherme Goettems Schneider

  • Fix table comment also being applied to the primary key column.

    Guilherme Goettems Schneider

  • Allow generated create_table migrations to include or skip timestamps.

    Michael Duchemin

Action View

  • SanitizeHelper.sanitized_allowed_attributes and SanitizeHelper.sanitized_allowed_tags call safe_list_sanitizer's class method

    Fixes #​39586

    Taufiq Muhammadi

  • Change form_with to generate non-remote forms by default.

    form_with would generate a remote form by default. This would confuse users because they were forced to handle remote requests.

    All new 6.1 applications will generate non-remote forms by default. When upgrading a 6.0 application you can enable remote forms by default by setting config.action_view.form_with_generates_remote_forms to true.

    Petrik de Heus

  • Yield translated strings to calls of ActionView::FormBuilder#button when a block is given.

    Sean Doyle

  • Alias ActionView::Helpers::Tags::Label::LabelBuilder#translation to #to_s so that form.label calls can yield that value to their blocks.

    Sean Doyle

  • Rename the new TagHelper#class_names method to TagHelper#token_list, and make the original available as an alias.

    token_list("foo", "foo bar")

=> "foo bar"

*Sean Doyle*
  • ARIA Array and Hash attributes are treated as space separated DOMTokenList values. This is useful when declaring lists of label text identifiers in aria-labelledby or aria-describedby.

    tag.input type: 'checkbox', name: 'published', aria: {
      invalid: @&#8203;post.errors[:published].any?,
      labelledby: ['published_context', 'published_label'],
      describedby: { published_errors: @&#8203;post.errors[:published].any? }
    }
    #=> <input
          type="checkbox" name="published" aria-invalid="true"
          aria-labelledby="published_context published_label"
          aria-describedby="published_errors"
        >

    Sean Doyle

  • Remove deprecated escape_whitelist from ActionView::Template::Handlers::ERB.

    Rafael Mendonça França

  • Remove deprecated find_all_anywhere from ActionView::Resolver.

    Rafael Mendonça França

  • Remove deprecated formats from ActionView::Template::HTML.

    Rafael Mendonça França

  • Remove deprecated formats from ActionView::Template::RawFile.

    Rafael Mendonça França

  • Remove deprecated formats from ActionView::Template::Text.

    Rafael Mendonça França

  • Remove deprecated find_file from ActionView::PathSet.

    Rafael Mendonça França

  • Remove deprecated rendered_format from ActionView::LookupContext.

    Rafael Mendonça França

  • Remove deprecated find_file from ActionView::ViewPaths.

    Rafael Mendonça França

  • Require that ActionView::Base subclasses implement #compiled_method_container.

    Rafael Mendonça França

  • Remove deprecated support to pass an object that is not a ActionView::LookupContext as the first argument in ActionView::Base#initialize.

    Rafael Mendonça França

  • Remove deprecated format argument ActionView::Base#initialize.

    Rafael Mendonça França

  • Remove deprecated ActionView::Template#refresh.

    Rafael Mendonça França

  • Remove deprecated ActionView::Template#original_encoding.

    Rafael Mendonça França

  • Remove deprecated ActionView::Template#variants.

    Rafael Mendonça França

  • Remove deprecated ActionView::Template#formats.

    Rafael Mendonça França

  • Remove deprecated ActionView::Template#virtual_path=.

    Rafael Mendonça França

  • Remove deprecated ActionView::Template#updated_at.

    Rafael Mendonça França

  • Remove deprecated updated_at argument required on ActionView::Template#initialize.

    Rafael Mendonça França

  • Make locals argument required on ActionView::Template#initialize.

    Rafael Mendonça França

  • Remove deprecated ActionView::Template.finalize_compiled_template_methods.

    Rafael Mendonça França

  • Remove deprecated config.action_view.finalize_compiled_template_methods

    Rafael Mendonça França

  • Remove deprecated support to calling ActionView::ViewPaths#with_fallback with a block.

    Rafael Mendonça França

  • Remove deprecated support to passing absolute paths to render template:.

    Rafael Mendonça França

  • Remove deprecated support to passing relative paths to render file:.

    Rafael Mendonça França

  • Remove support to template handlers that don't accept two arguments.

    Rafael Mendonça França

  • Remove deprecated pattern argument in ActionView::Template::PathResolver.

    Rafael Mendonça França

  • Remove deprecated support to call private methods from object in some view helpers.

    Rafael Mendonça França

  • ActionView::Helpers::TranslationHelper#translate accepts a block, yielding the translated text and the fully resolved translation key:

    <%= translate(".relative_key") do |translation, resolved_key| %>
      <span title="<%= resolved_key %>"><%= translation %></span>
    <% end %>

    Sean Doyle

  • Ensure cache fragment digests include all relevant template dependencies when fragments are contained in a block passed to the render helper. Remove the virtual_path keyword arguments found in CacheHelper as they no longer possess any function following 1581cab.

    Fixes #​38984.

    Aaron Lipman

  • Deprecate config.action_view.raise_on_missing_translations in favor of config.i18n.raise_on_missing_translations.

    New generalized configuration option now determines whether an error should be raised for missing translations in controllers and views.

    fatkodima

  • Instrument layout rendering in TemplateRenderer#render_with_layout as render_layout.action_view, and include (when necessary) the layout's virtual path in notification payloads for collection and partial renders.

    Zach Kemp

  • ActionView::Base.annotate_rendered_view_with_filenames annotates HTML output with template file names.

    Joel Hawksley, Aaron Patterson

  • ActionView::Helpers::TranslationHelper#translate returns nil when passed default: nil without a translation matching I18n#translate.

    Stefan Wrobel

  • OptimizedFileSystemResolver prefers template details in order of locale, formats, variants, handlers.

    Iago Pimenta

  • Added class_names helper to create a CSS class value with conditional classes.

    Joel Hawksley, Aaron Patterson

  • Add support for conditional values to TagBuilder.

    Joel Hawksley

  • ActionView::Helpers::FormOptionsHelper#select should mark option for nil as selected.

    @&#8203;post = Post.new
    @&#8203;post.category = nil

Before

select("post", "category", none: nil, programming: 1, economics: 2)

=>

none

programming

economics

After

select("post", "category", none: nil, programming: 1, economics: 2)

=>

none

programming

economics

```

*bogdanvlviv*
  • Log lines for partial renders and started template renders are now emitted at the DEBUG level instead of INFO.

    Completed template renders are still logged at the INFO level.

    DHH

  • ActionView::Helpers::SanitizeHelper: support rails-html-sanitizer 1.1.0.

    Juanito Fatas

  • Added phone_to helper method to create a link from mobile numbers.

    Pietro Moro

  • annotated_source_code returns an empty array so TemplateErrors without a template in the backtrace are surfaced properly by DebugExceptions.

    Guilherme Mansur, Kasper Timm Hansen

  • Add autoload for SyntaxErrorInTemplate so syntax errors are correctly raised by DebugExceptions.

    Guilherme Mansur, Gannon McGibbon

  • RenderingHelper supports rendering objects that respond_to? :render_in.

    Joel Hawksley, Natasha Umer, Aaron Patterson, Shawn Allen, Emily Plummer, Diana Mounter, John Hawthorn, Nathan Herald, Zaid Zawaideh, Zach Ahn

  • Fix select_tag so that it doesn't change options when include_blank is present.

    Younes SERRAJ

Action Pack

  • Support for the HTTP header Feature-Policy has been revised to reflect its rename to Permissions-Policy.

    Rails.application.config.permissions_policy do |p|
      p.camera     :none
      p.gyroscope  :none
      p.microphone :none
      p.usb        :none
      p.fullscreen :self
      p.payment    :self, "https://secure-example.com"
    end

    Julien Grillot

  • Allow ActionDispatch::HostAuthorization to exclude specific requests.

    Host Authorization checks can be skipped for specific requests. This allows for health check requests to be permitted for requests with missing or non-matching host headers.

    Chris Bisnett

  • Add config.action_dispatch.request_id_header to allow changing the name of the unique X-Request-Id header

    Arlston Fernandes

  • Deprecate config.action_dispatch.return_only_media_type_on_content_type.

    Rafael Mendonça França

  • Change ActionDispatch::Response#content_type to return the full Content-Type header.

    Rafael Mendonça França

  • Remove deprecated ActionDispatch::Http::ParameterFilter.

    Rafael Mendonça França

  • Added support for exclusive no-store Cache-Control header.

    If no-store is set on Cache-Control header it is exclusive (all other cache directives are dropped).

    Chris Kruger

  • Catch invalid UTF-8 parameters for POST requests and respond with BadRequest.

    Additionally, perform #set_binary_encoding in ActionDispatch::Http::Request#GET and ActionDispatch::Http::Request#POST prior to validating encoding.

    Adrianna Chang

  • Allow assert_recognizes routing assertions to work on mounted root routes.

    Gannon McGibbon

  • Change default redirection status code for non-GET/HEAD requests to 308 Permanent Redirect for ActionDispatch::SSL.

    Alan Tan, Oz Ben-David

  • Fix follow_redirect! to follow redirection with same HTTP verb when following a 308 redirection.

    Alan Tan

  • When multiple domains are specified for a cookie, a domain will now be chosen only if it is equal to or is a superdomain of the request host.

    Jonathan Hefner

  • ActionDispatch::Static handles precompiled Brotli (.br) files.

    Adds to existing support for precompiled gzip (.gz) files. Brotli files are preferred due to much better compression.

    When the browser requests /some.js with Accept-Encoding: br, we check for public/some.js.br and serve that file, if present, with Content-Encoding: br and Vary: Accept-Encoding headers.

    Ryan Edward Hall, Jeremy Daer

  • Add raise_on_missing_translations support for controllers.

    This configuration determines whether an error should be raised for missing translations. It can be enabled through config.i18n.raise_on_missing_translations. Note that described configuration also affects raising error for missing translations in views.

    fatkodima

  • Added compact and compact! to ActionController::Parameters.

    Eugene Kenny

  • Calling each_pair or each_value on an ActionController::Parameters without passing a block now returns an enumerator.

    Eugene Kenny

  • fixture_file_upload now uses path relative to file_fixture_path

    Previously the path had to be relative to fixture_path. You can change your existing code as follow:

Before

fixture_file_upload('files/dog.png')

After

fixture_file_upload('dog.png')
```

*Edouard Chin*
  • Remove deprecated force_ssl at the controller level.

    Rafael Mendonça França

  • The +helper+ class method for controllers loads helper modules specified as strings/symbols with String#constantize instead of require_dependency.

    Remember that support for strings/symbols is only a convenient API. You can always pass a module object:

    helper UtilsHelper

    which is recommended because it is simple and direct. When a string/symbol is received, helper just manipulates and inflects the argument to obtain that same module object.

    Xavier Noria, Jean Boussier

  • Correctly identify the entire localhost IPv4 range as trusted proxy.

    Nick Soracco

  • url_for will now use "https://" as the default protocol when Rails.application.config.force_ssl is set to true.

    Jonathan Hefner

  • Accept and default to base64_urlsafe CSRF tokens.

    Base64 strict-encoded CSRF tokens are not inherently websafe, which makes them difficult to deal with. For example, the common practice of sending the CSRF token to a browser in a client-readable cookie does not work properly out of the box: the value has to be url-encoded and decoded to survive transport.

    Now, we generate Base64 urlsafe-encoded CSRF tokens, which are inherently safe to transport. Validation accepts both urlsafe tokens, and strict-encoded tokens for backwards compatibility.

    Scott Blum

  • Support rolling deploys for cookie serialization/encryption changes.

    In a distributed configuration like rolling update, users may observe both old and new instances during deployment. Users may be served by a new instance and then by an old instance.

    That means when the server changes cookies_serializer from :marshal to :hybrid or the server changes use_authenticated_cookie_encryption from false to true, users may lose their sessions if they access the server during deployment.

    We added fallbacks to downgrade the cookie format when necessary during deployment, ensuring compatibility on both old and new instances.

    Masaki Hara

  • ActionDispatch::Request.remote_ip has ip address even when all sites are trusted.

    Before, if all X-Forwarded-For sites were trusted, the remote_ip would default to 127.0.0.1. Now, the furthest proxy site is used. e.g.: It now gives an ip address when using curl from the load balancer.

    Keenan Brock

  • Fix possible information leak / session hijacking vulnerability.

    The ActionDispatch::Session::MemcacheStore is still vulnerable given it requires the gem dalli to be updated as well.

    CVE-2019-16782.

  • Include child session assertion count in ActionDispatch::IntegrationTest.

    IntegrationTest#open_session uses dup to create the new session, which meant it had its own copy of @assertions. This prevented the assertions from being correctly counted and reported.

    Child sessions now have their attr_accessor overridden to delegate to the root session.

    Fixes #​32142.

    Sam Bostock

  • Add SameSite protection to every written cookie.

    Enabling SameSite cookie protection is an addition to CSRF protection, where cookies won't be sent by browsers in cross-site POST requests when set to :lax.

    :strict disables cookies being sent in cross-site GET or POST requests.

    Passing :none disables this protection and is the same as previous versions albeit a ; SameSite=None is appended to the cookie.

    See upgrade instructions in config/initializers/new_framework_defaults_6_1.rb.

    More info here

    NB: Technically already possible as Rack supports SameSite protection, this is to ensure it's applied to all cookies

    Cédric Fabianski

  • Bring back the feature that allows loading external route files from the router.

    This feature existed back in 2012 but got reverted with the incentive that https://github.com/rails/routing_concerns was a better approach. Turned out that this wasn't fully the case and loading external route files from the router can be helpful for applications with a really large set of routes. Without this feature, application needs to implement routes reloading themselves and it's not straightforward.

config/routes.rb

Rails.application.routes.draw do
  draw(:admin)
end

config/routes/admin.rb

get :foo, to: 'foo#bar'
```

*Yehuda Katz*, *Edouard Chin*
  • Fix system test driver option initialization for non-headless browsers.

    glaszig

  • redirect_to.action_controller notifications now include the ActionDispatch::Request in their payloads as :request.

    Austin Story

  • respond_to#any no longer returns a response's Content-Type based on the request format but based on the block given.

    Example:

      def my_action
        respond_to do |format|
          format.any { render(json: { foo: 'bar' }) }
        end
      end
    
      get('my_action.csv')

    The previous behaviour was to respond with a text/csv Content-Type which is inaccurate since a JSON response is being rendered.

    Now it correctly returns a application/json Content-Type.

    Edouard Chin

  • Replaces (back)slashes in failure screenshot image paths with dashes.

    If a failed test case contained a slash or a backslash, a screenshot would be created in a nested directory, causing issues with tmp:clear.

    Damir Zekic

  • Add params.member? to mimic Hash behavior.

    Younes Serraj

  • process_action.action_controller notifications now include the following in their payloads:

    • :request - the ActionDispatch::Request
    • :response - the ActionDispatch::Response

    George Claghorn

  • Updated ActionDispatch::Request.remote_ip setter to clear set the instance remote_ip to nil before setting the header that the value is derived from.

    Fixes #​37383.

    Norm Provost

  • ActionController::Base.log_at allows setting a different log level per request.

Use the debug level if a particular cookie is set.

class ApplicationController < ActionController::Base
  log_at :debug, if: -> { cookies[:debug] }
end
```

*George Claghorn*
  • Allow system test screen shots to be taken more than once in a test by prefixing the file name with an incrementing counter.

    Add an environment variable RAILS_SYSTEM_TESTING_SCREENSHOT_HTML to enable saving of HTML during a screenshot in addition to the image. This uses the same image name, with the extension replaced with .html

    Tom Fakes

  • Add Vary: Accept header when using Accept header for response.

    For some requests like /users/1, Rails uses requests' Accept header to determine what to return. And if we don't add Vary in the response header, browsers might accidentally cache different types of content, which would cause issues: e.g. javascript got displayed instead of html content. This MR fixes these issues by adding Vary: Accept in these types of requests. For more detailed problem description, please read:

    https://github.com/rails/rails/pull/36213

    Fixes #​25842.

    Stan Lo

  • Fix IntegrationTest follow_redirect! to follow redirection using the same HTTP verb when following a 307 redirection.

    Edouard Chin

  • System tests require Capybara 3.26 or newer.

    George Claghorn

  • Reduced log noise handling ActionController::RoutingErrors.

    Alberto Fernández-Capel

  • Add DSL for configuring HTTP Feature Policy.

    This new DSL provides a way to configure an HTTP Feature Policy at a global or per-controller level. Full details of HTTP Feature Policy specification and guidelines can be found at MDN:

    https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Feature-Policy

    Example global policy:

    Rails.application.config.feature_policy do |f|
      f.camera      :none
      f.gyroscope   :none
      f.microphone  :none
      f.usb         :none
      f.fullscreen  :self
      f.payment     :self, "https://secure.example.com"
    end

    Example controller level policy:

    class PagesController < ApplicationController
      feature_policy do |p|
        p.geolocation "https://example.com"
      end
    end

    Jacob Bednarz

  • Add the ability to set the CSP nonce only to the specified directives.

    Fixes #​35137.

    Yuji Yaginuma

  • Keep part when scope option has value.

    When a route was defined within an optional scope, if that route didn't take parameters the scope was lost when using path helpers. This commit ensures scope is kept both when the route takes parameters or when it doesn't.

    Fixes #​33219.

    Alberto Almagro

  • Added deep_transform_keys and deep_transform_keys! methods to ActionController::Parameters.

    Gustavo Gutierrez

  • Calling ActionController::Parameters#transform_keys/! without a block now returns an enumerator for the parameters instead of the underlying hash.

    Eugene Kenny

  • Fix strong parameters blocks all attributes even when only some keys are invalid (non-numerical). It should only block invalid key's values instead.

    Stan Lo

Active Job

  • Recover nano precision when serializing Time, TimeWithZone and DateTime objects.

    Alan Tan

  • Deprecate config.active_job.return_false_on_aborted_enqueue.

    Rafael Mendonça França

  • Return false when enqueuing a job is aborted.

    Rafael Mendonça França

  • While using perform_enqueued_jobs test helper enqueued jobs must be stored for the later check with assert_enqueued_with.

    Dmitry Polushkin

  • ActiveJob::TestCase#perform_enqueued_jobs without a block removes performed jobs from the queue.

    That way the helper can be called multiple times and not perform a job invocation multiple times.

    def test_jobs
      HelloJob.perform_later("rafael")
      perform_enqueued_jobs # only runs with "rafael"
      HelloJob.perform_later("david")
      perform_enqueued_jobs # only runs with "david"
    end

    Étienne Barrié

  • ActiveJob::TestCase#perform_enqueued_jobs will no longer perform retries:

    When calling perform_enqueued_jobs without a block, the adapter will now perform jobs that are already in the queue. Jobs that will end up in the queue afterwards won't be performed.

    This change only affects perform_enqueued_jobs when no block is given.

    Edouard Chin

  • Add queue name support to Que adapter.

    Brad Nauta, Wojciech Wnętrzak

  • Don't run after_enqueue and after_perform callbacks if the callback chain is halted.

    class MyJob < ApplicationJob
      before_enqueue { throw(:abort) }
      after_enqueue { # won't enter here anymore }
    end

    after_enqueue and after_perform callbacks will no longer run if the callback chain is halted. This behaviour is a breaking change and won't take effect until Rails 6.2. To enable this behaviour in your app right now, you can add in your app's configuration file config.active_job.skip_after_callbacks_if_terminated = true.

    Edouard Chin

  • Fix enqueuing and performing incorrect logging message.

    Jobs will no longer always log "Enqueued MyJob" or "Performed MyJob" when they actually didn't get enqueued/performed.

      class MyJob < ApplicationJob
        before_enqueue { throw(:abort) }
      end
    
      MyJob.perform_later # Will no longer log "Enqueued MyJob" since job wasn't even enqueued through adapter.

    A new message will be logged in case a job couldn't be enqueued, either because the callback chain was halted or because an exception happened during enqueuing. (i.e. Redis is down when you try to enqueue your job)

    Edouard Chin

  • Add an option to disable logging of the job arguments when enqueuing and executing the job.

    class SensitiveJob < ApplicationJob
      self.log_arguments = false
    
      def perform(my_sensitive_argument)
      end
    end

    When dealing with sensitive arguments as password and tokens it is now possible to configure the job to not put the sensitive argument in the logs.

    Rafael Mendonça França

  • Changes in queue_name_prefix of a job no longer affects all other jobs.

    Fixes #​37084.

    Lucas Mansur

  • Allow Class and Module instances to be serialized.

    Kevin Deisz

  • Log potential matches in assert_enqueued_with and assert_performed_with.

    Gareth du Plooy

  • Add at argument to the perform_enqueued_jobs test helper.

    John Crepezzi, Eileen Uchitelle

  • assert_enqueued_with and assert_performed_with can now test jobs with relative delay.

    Vlado Cingel

  • Add jitter to ActiveJob::Exceptions.retry_on.

    ActiveJob::Exceptions.retry_on now uses a random amount of jitter in order to prevent the thundering herd effect. Defaults to 15% (represented as 0.15) but overridable via the :jitter option when using retry_on. Jitter is applied when an Integer, ActiveSupport::Duration or :exponentially_longer, is passed to the wait argument in retry_on.

    retry_on(MyError, wait: :exponentially_longer, jitter: 0.30)

    Anthony Ross

Action Mailer

  • Change default queue name of the deliver (:mailers) job to be the job adapter's default (:default).

    Rafael Mendonça França

  • Remove deprecated ActionMailer::Base.receive in favor of Action Mailbox.

    Rafael Mendonça França

  • Fix ActionMailer assertions don't work for parameterized mail with legacy delivery job.

    bogdanvlviv

  • Added email_address_with_name to properly escape addresses with names.

    Sunny Ripert

Action Cable

  • ActionCable::Connection::Base now allows intercepting unhandled exceptions with rescue_from before they are logged, which is useful for error reporting tools and other integrations.

    Justin Talbott

  • Add ActionCable::Channel#stream_or_reject_for to stream if record is present, otherwise reject the connection

    Atul Bhosale

  • Add ActionCable::Channel#stop_stream_from and #stop_stream_for to unsubscribe from a specific stream.

    Zhang Kang

  • Add PostgreSQL subscription connection identificator.

    Now you can distinguish Action Cable PostgreSQL subscription connections among others. Also, you can set custom id in cable.yml configuration.

    SELECT application_name FROM pg_stat_activity;
    /*
        application_name
    ------------------------
    psql
    ActionCable-PID-42
    (2 rows)
    */

    Sergey Ponomarev

  • Subscription confirmations and rejections are now logged at the DEBUG level instead of INFO.

    DHH

Active Storage

  • Change default queue name of the analysis (:active_storage_analysis) and purge (:active_storage_purge) jobs to be the job adapter's default (:default).

    Rafael Mendonça França

  • Implement strict_loading on ActiveStorage associations.

    David Angulo

  • Remove deprecated support to pass :combine_options operations to ActiveStorage::Transformers::ImageProcessing.

    Rafael Mendonça França

  • Remove deprecated ActiveStorage::Transformers::MiniMagickTransformer.

    Rafael Mendonça França

  • Remove deprecated config.active_storage.queue.

    Rafael Mendonça França

  • Remove deprecated ActiveStorage::Downloading.

    Rafael Mendonça França

  • Add per-environment configuration support

    Pietro Moro

  • The Poppler PDF previewer renders a preview image using the original document's crop box rather than its media box, hiding print margins. This matches the behavior of the MuPDF previewer.

    Vincent Robert

  • Touch parent model when an attachment is purged.

    Víctor Pérez Rodríguez

  • Files can now be served by proxying them from the underlying storage service instead of redirecting to a signed service URL. Use the rails_storage_proxy_path and _url helpers to proxy an attached file:

    <%= image_tag rails_storage_proxy_path(@&#8203;user.avatar) %>

    To proxy by default, set config.active_storage.resolve_model_to_route:

Proxy attached files instead.

config.active_storage.resolve_model_to_route = :rails_storage_proxy
```

```erb
<%= image_tag @&#8203;user.avatar %>
```

To redirect to a signed service URL when the default file serving strategy
is set to proxying, use the `rails_storage_redirect_path` and `_url` helpers:

```erb
<%= image_tag rails_storage_redirect_path(@&#8203;user.avatar) %>
```

*Jonathan Fleckenstein*
  • Add config.active_storage.web_image_content_types to allow applications to add content types (like image/webp) in which variants can be processed, instead of letting those images be converted to the fallback PNG format.

    Jeroen van Haperen

  • Add support for creating variants of WebP images out of the box.

    Dino Maric

  • Only enqueue analysis jobs for blobs with non-null analyzer classes.

    Gannon McGibbon

  • Previews are created on the same service as the original blob.

    Peter Zhu

  • Remove unused disposition and content_type query parameters for DiskService.

    Peter Zhu

  • Use DiskController for both public and private files.

    DiskController is able to handle multiple services by adding a service_name field in the generated URL in DiskService.

    Peter Zhu

  • Variants are tracked in the database to avoid existence checks in the storage service.

    George Claghorn

  • Deprecate service_url methods in favour of url.

    Deprecate Variant#service_url and Preview#service_url to instead use #url method to be consistent with Blob.

    Peter Zhu

  • Permanent URLs for public storage blobs.

    Services can be configured in config/storage.yml with a new key public: true | false to indicate whether a service holds public blobs or private blobs. Public services will always return a permanent URL.

    Deprecates Blob#service_url in favor of Blob#url.

    Peter Zhu

  • Make services aware of configuration names.

    Gannon McGibbon

  • The Content-Type header is set on image variants when they're uploaded to third-party storage services.

    Kyle Ribordy

  • Allow storage services to be configured per attachment.

    class User < ActiveRecord::Base
      has_one_attached :avatar, service: :s3
    end
    
    class Gallery < ActiveRecord::Base
      has_many_attached :photos, service: :s3
    end

    Dmitry Tsepelev

  • You can optionally provide a custom blob key when attaching a new file:

    user.avatar.attach key: "avatars/#{user.id}.jpg",
      io: io, content_type: "image/jpeg", filename: "avatar.jpg"

    Active Storage will store the blob's data on the configured service at the provided key.

    George Claghorn

  • Replace Blob.create_after_upload! with Blob.create_and_upload! and deprecate the former.

    create_after_upload! has been removed since it could lead to data corruption by uploading to a key on the storage service which happened to be already taken. Creating the record would then correctly raise a database uniqueness exception but the stored object would already have overwritten another. create_and_upload! swaps the order of operations so that the key gets reserved up-front or the uniqueness error gets raised, before the upload to a key takes place.

    Julik Tarkhanov

  • Set content disposition in direct upload using filename and disposition parameters to ActiveStorage::Service#headers_for_direct_upload.

    Peter Zhu

  • Allow record to be optionally passed to blob finders to make sharding easier.

    Gannon McGibbon

  • Switch from azure-storage gem to azure-storage-blob gem for Azure service.

    Peter Zhu

  • Add config.active_storage.draw_routes to disable Active Storage routes.

    Gannon McGibbon

  • Image analysis is skipped if ImageMagick returns an error.

    ActiveStorage::Analyzer::ImageAnalyzer#metadata would previously raise a MiniMagick::Error, which caused persistent ActiveStorage::AnalyzeJob failures. It now logs the error and returns {}, resulting in no metadata being added to the offending image blob.

    George Claghorn

  • Method calls on singular attachments return nil when no file is attached.

    Previously, assuming the following User model, user.avatar.filename would raise a Module::DelegationError if no avatar was attached:

    class User < ApplicationRecord
      has_one_attached :avatar
    end

    They now return nil.

    Matthew Tanous

  • The mirror service supports direct uploads.

    New files are directly uploaded to the primary service. When a directly-uploaded file is attached to a record, a background job is enqueued to copy it to each secondary service.

    Configure the queue used to process mirroring jobs by setting config.active_storage.queues.mirror. The default is :active_storage_mirror.

    George Claghorn

  • The S3 service now permits uploading files larger than 5 gigabytes.

    When uploading a file greater than 100 megabytes in size, the service transparently switches to multipart uploads using a part size computed from the file's total size and S3's part count limit.

    No application changes are necessary to take advantage of this feature. You can customize the default 100 MB multipart upload threshold in your S3 service's configuration:

    production:
      service: s3
      access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
      secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
      region: us-east-1
      bucket: my-bucket
      upload:
        multipart_threshold: <%= 250.megabytes %>

    George Claghorn

Action Mailbox

  • Change default queue name of the incineration (:action_mailbox_incineration) and routing (:action_mailbox_routing) jobs to be the job adapter's default (:default).

    Rafael Mendonça França

  • Sendgrid ingress now passes through the envelope recipient as X-Original-To.

    Mark Haussmann

  • Update Mandrill inbound email route to respond appropriately to HEAD requests for URL health checks from Mandrill.

    Bill Cromie

  • Add way to deliver emails via source instead of filling out a form through the conductor interface.

    DHH

  • Mailgun ingress now passes through the envelope recipient as X-Original-To.

    Rikki Pitt

  • Deprecate Rails.application.credentials.action_mailbox.api_key and MAILGUN_INGRESS_API_KEY in favor of Rails.application.credentials.action_mailbox.signing_key and MAILGUN_INGRESS_SIGNING_KEY.

    Matthijs Vos

  • Allow easier creation of multi-part emails from the create_inbound_email_from_mail and receive_inbound_email_from_mail test helpers.

    Michael Herold

  • Fix Bcc header not being included with emails from create_inbound_email_from test helpers.

    jduff

  • Add ApplicationMailbox.mailbox_for to expose mailbox routing.

    James Dabbs

Action Text

  • Declare ActionText::FixtureSet.attachment to generate an <action-text-attachment sgid="..."></action-text-attachment> element with a valid sgid attribute.

    hello_world_review_content:
      record: hello_world (Review)
      name: content
      body: <p><%= ActionText::FixtureSet.attachment("messages", :hello_world) %> is great!</p>

    Sean Doyle

  • Locate fill_in_rich_text_area by <label> text

    In addition to searching for <trix-editor> elements with the appropriate aria-label attribute, also support locating elements that match the corresponding <label> element's text.

    Sean Doyle

  • Be able to add a default value to rich_text_area.

    form.rich_text_area :content, value: "<h1>Hello world</h1>"
    #=> <input type="hidden" name="message[content]" id="message_content_trix_input_message_1" value="<h1>Hello world</h1>">

    Paulo Ancheta

  • Add method to confirm rich text content existence by adding ? after rich text attribute.

    message = Message.create!(body: "<h1>Funny times!</h1>")
    message.body? #=> true

    Kyohei Toyoda

  • The fill_in_rich_text_area system test helper locates a Trix editor and fills it in with the given HTML.

<trix-editor id="message_content" ...>

fill_in_rich_text_area "message_content", with: "Hello <em>world!</em>"

<trix-editor placeholder="Your message here" ...>

fill_in_rich_text_area "Your message here", with: "Hello <em>world!</em>"

<trix-editor aria-label="Message content" ...>

fill_in_rich_text_area "Message content", with: "Hello <em>world!</em>"

fill_in_rich_text_area "message[content]", with: "Hello <em>world!</em>"
```

*George Claghorn*

Railties

  • Added Railtie#server hook called when Rails starts a server. This is useful in case your application or a library needs to run another process next to the Rails server. This is quite common in development for instance to run the Webpack or the React server.

    It can be used like this:

      class MyRailtie < Rails::Railtie
        server do
          WebpackServer.run
        end
      end

    Edouard Chin

  • Remove deprecated rake dev:cache tasks.

    Rafael Mendonça França

  • Remove deprecated rake routes tasks.

    Rafael Mendonça França

  • Remove deprecated rake initializers tasks.

    Rafael Mendonça França

  • Remove deprecated support for using the HOST environment variable to specify the server IP.

    Rafael Mendonça França

  • Remove deprecated server argument from the rails server command.

    Rafael Mendonça França

  • Remove deprecated SOURCE_ANNOTATION_DIRECTORIES environment variable support from rails notes.

    Rafael Mendonça França

  • Remove deprecated connection option in the rails dbconsole command.

    Rafael Mendonça França

  • Remove depreated rake notes tasks.

    Rafael Mendonça França

  • Return a 405 Method Not Allowed response when a request uses an unknown HTTP method.

    Fixes #​38998.

    Loren Norman

  • Make railsrc file location xdg-specification compliant

    rails new will now look for the default railsrc file at $XDG_CONFIG_HOME/rails/railsrc (or ~/.config/rails/railsrc if XDG_CONFIG_HOME is not set). If this file does not exist, rails new will fall back to ~/.railsrc.

    The fallback behaviour means this does not cause any breaking changes.

    Nick Wolf

  • Change the default logging level from :debug to :info to avoid inadvertent exposure of personally identifiable information (PII) in production environments.

    Eric M. Payne

  • Automatically generate abstract class when using multiple databases.

    When generating a scaffold for a multiple database application, Rails will now automatically generate the abstract class for the database when the database argument is passed. This abstract class will include the connection information for the writing configuration and any models generated for that database will automatically inherit from the abstract class.

    Usage:

    $ bin/rails generate scaffold Pet name:string --database=animals

    Will create an abstract class for the animals connection.

    class AnimalsRecord < ApplicationRecord
      self.abstract_class = true
    
      connects_to database: { writing: :animals }
    end

    And generate a Pet model that inherits from the new AnimalsRecord:

    class Pet < AnimalsRecord
    end

    If you already have an abstract class and it follows a different pattern than Rails defaults, you can pass a parent class with the database argument.

    $ bin/rails generate scaffold Pet name:string --database=animals --parent=SecondaryBase

    This will ensure the model inherits from the SecondaryBase parent instead of AnimalsRecord

    class Pet < SecondaryBase
    end

    Eileen M. Uchitelle, John Crepezzi

  • Accept params from url to prepopulate the Inbound Emails form in Rails conductor.

    Chris Oliver

  • Create a new rails app using a minimal stack.

    rails new cool_app --minimal

    All the following are excluded from your minimal stack:

    • action_cable
    • action_mailbox
    • action_mailer
    • action_text
    • active_job
    • active_storage
    • bootsnap
    • jbuilder
    • spring
    • system_tests
    • turbolinks
    • webpack

    Haroon Ahmed, DHH

  • Add default ENV variable option with BACKTRACE to turn off backtrace cleaning when debugging framework code in the generated config/initializers/backtrace_silencers.rb.

    BACKTRACE=1 ./bin/rails runner "MyClass.perform"

    DHH

  • The autoloading guide for Zeitwerk mode documents how to autoload classes during application boot in a safe way.

    Haroon Ahmed, Xavier Noria

  • The classic autoloader starts its deprecation cycle.

    New Rails projects are strongly discouraged from using classic, and we recommend that existing projects running on classic switch to zeitwerk mode when upgrading. Please check the Upgrading Ruby on Rails guide for tips.

    Xavier Noria

  • Adds rails test:all for running all tests in the test directory.

    This runs all test files in the test directory, including system tests.

    Niklas Häusele

  • Add config.generators.after_generate for processing to generated files.

    Register a callback that will get called right after generators has finished.

    Yuji Yaginuma

  • Make test file patterns configurable via Environment variables

    This makes test file patterns configurable via two environment variables: DEFAULT_TEST, to configure files to test, and DEFAULT_TEST_EXCLUDE, to configure files to exclude from testing.

    These values were hardcoded before, which made it difficult to add new categories of tests that should not be executed by default (e.g: smoke tests).

    Jorge Manrubia

  • No longer include rake rdoc task when generating plugins.

    To generate docs, use the rdoc lib command instead.

    Jonathan Hefner

  • Allow relative paths with trailing slashes to be passed to rails test.

    Eugene Kenny

  • Add rack-mini-profiler gem to the default Gemfile.

    rack-mini-profiler displays performance information such as SQL time and flame graphs. It's enabled by default in development environment, but can be enabled in production as well. See the gem README for information on how to enable it in production.

    Osama Sayegh

  • rails stats will now count TypeScript files toward JavaScript stats.

    Joshua Cody

  • Run git init when generating plugins.

    Opt out with --skip-git.

    OKURA Masafumi

  • Add benchmark generator.

    Introduce benchmark generator to benchmark Rails applications.

    rails generate benchmark opt_compare

    This creates a benchmark file that uses benchmark-ips. By default, two code blocks can be benchmarked using the before and after reports.

    You can run the generated benchmark file using: ruby script/benchmarks/opt_compare.rb

    Kevin Jalbert, Gannon McGibbon

  • Cache compiled view templates when running tests by default.

    When generating a new app without --skip-spring, caching classes is disabled in environments/test.rb. This implicitly disables caching view templates too. This change will enable view template caching by adding this to the generated environments/test.rb:

    config.action_view.cache_template_loading = true

    Jorge Manrubia

  • Introduce middleware move operations.

    With this change, you no longer need to delete and reinsert a middleware to move it from one place to another in the stack:

    config.middleware.move_before ActionDispatch::Flash, Magical::Unicorns

    This will move the Magical::Unicorns middleware before ActionDispatch::Flash. You can also move it after with:

    config.middleware.move_after ActionDispatch::Flash, Magical::Unicorns

    Genadi Samokovarov

  • Generators that inherit from NamedBase respect --force option.

    Josh Brody

  • Allow configuration of eager_load behaviour for rake environment:

    config.rake_eager_load

    Defaults to false as per previous behaviour.

    Thierry Joyal

  • Ensure Rails migration generator respects system-wide primary key config.

    When rails is configured to use a specific primary key type:

    config.generators do |g|
      g.orm :active_record, primary_key_type: :uuid
    end

    Previously:

    $ bin/rails g migration add_location_to_users location:references

    The references line in the migration would not have type: :uuid. This change causes the type to be applied appropriately.

    Louis-Michel Couture, Dermot Haughey

  • Deprecate Rails::DBConsole#config.

    Rails::DBConsole#config is deprecated without replacement. Use Rails::DBConsole.db_config.configuration_hash instead.

    Eileen M. Uchitelle, John Crepezzi

  • Rails.application.config_for merges shared configuration deeply.

config/example.yml

shared:
  foo:
    bar:
      baz: 1
development:
  foo:
    bar:
      qux: 2
```

```ruby

Previously

Rails.application.config_for(:example)[:foo][:bar] #=> { qux: 2 }

Now

Rails.application.config_for(:example)[:foo][:bar] #=> { baz: 1, qux: 2 }
```

*Yuhei Kiriyama*
  • Remove access to values in nested hashes returned by Rails.application.config_for via String keys.

config/example.yml

development:
  options:
    key: value
```

```ruby
Rails.application.config_for(:example).options
```

This used to return a Hash on which you could access values with String keys. This was deprecated in 6.0, and now doesn't work anymore.

*Étienne Barrié*
  • Configuration files for environments (config/environments/*.rb) are now able to modify autoload_paths, autoload_once_paths, and eager_load_paths.

    As a consequence, applications cannot autoload within those files. Before, they technically could, but changes in autoloaded classes or modules had no effect anyway in the configuration because reloading does not reboot.

    Ways to use application code in these files:

    • Define early in the boot process a class that is not reloadable, from which the application takes configuration values that get passed to the framework.

In config/application.rb, for example.

    require "#{Rails.root}/lib/my_app/config"

In config/environments/development.rb, for example.

    config.foo = MyApp::Config.foo
    ```

* If the class has to be reloadable, then wrap the configuration code in a `to_prepare` block:

    ```ruby
    config.to_prepare do
      config.foo = MyModel.foo
    end
    ```

  That assigns the latest `MyModel.foo` to `config.foo` when the application boots, and each time there is a reload. But whether that has an effect or not depends on the configuration point, since it is not uncommon for engines to read the application configuration during initialization and set their own state from them. That process happens only on boot, not on reloads, and if that is how `config.foo` worked, resetting it would have no effect in the state of the engine.

*Allen Hsu* & *Xavier Noria*
  • Support using environment variable to set pidfile.

    Ben Thorner

v6.0.6.1

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • Make sanitize_as_sql_comment more strict

    Though this method was likely never meant to take user input, it was attempting sanitization. That sanitization could be bypassed with carefully crafted input.

    This commit makes the sanitization more robust by replacing any occurrances of "/" or "/" with "/ " or " /". It also performs a first pass to remove one surrounding comment to avoid compatibility issues for users relying on the existing removal.

    This also clarifies in the documentation of annotate that it should not be provided user input.

    [CVE-2023-22794]

Action View

  • No changes.

Action Pack

  • No changes.

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.

v6.0.6

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • Symbol is allowed by default for YAML columns

    Étienne Barrié

Action View

  • No changes.

Action Pack

  • No changes.

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.

v6.0.5.1: 6.0.5.1

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • Change ActiveRecord::Coders::YAMLColumn default to safe_load

    This adds two new configuration options The configuration options are as follows:

    • config.active_storage.use_yaml_unsafe_load

    When set to true, this configuration option tells Rails to use the old "unsafe" YAML loading strategy, maintaining the existing behavior but leaving the possible escalation vulnerability in place. Setting this option to true is not recommended, but can aid in upgrading.

    • config.active_record.yaml_column_permitted_classes

    The "safe YAML" loading method does not allow all classes to be deserialized by default. This option allows you to specify classes deemed "safe" in your application. For example, if your application uses Symbol and Time in serialized data, you can add Symbol and Time to the allowed list as follows:

    config.active_record.yaml_column_permitted_classes = [Symbol, Date, Time]

    [CVE-2022-32224]

Action View

  • No changes.

Action Pack

  • No changes.

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.

v6.0.5: 6.0.5

Compare Source

Active Support

  • Fix tag helper regression.

    Eileen Uchitelle

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • No changes.

Action Pack

  • No changes.

Active Job

  • No changes.

Action Mailer

  • No changes.

Action Cable

  • No changes.

Active Storage

  • No changes.

Railties

  • No changes.

Action Text

  • Disentangle Action Text from ApplicationController

    Allow Action Text to be used without having an ApplicationController defined. This makes sure:

    • Action Text attachments render the correct URL host in mailers.
    • an ActionController::Renderer isn't allocated per request.
    • Sidekiq doesn't hang with the "classic" autoloader.

    Jonathan Hefner

v6.0.4.8: 6.0.4.8

Compare Source

Active Support

  • Fix and add protections for XSS in ActionView::Helpers and ERB::Util.

    Add the method ERB::Util.xml_name_escape to escape dangerous characters in names of tags and names of attributes, following the specification of XML.

    Álvaro Martín Fraguas

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • Fix and add protections for XSS in ActionView::Helpers and ERB::Util.

    Escape dangerous characters in names of tags and names of attributes in the tag helpers, following the XML specification. Rename the option :escape_attributes to :escape, to simplify by applying the option to the whole tag.

    Álvaro Martín Fraguas

Action Pack

  • Allow Content Security Policy DSL to generate for API responses.

    Tim Wade

Active Job

  • No changes.

Action Mailer

  • No changes.

Action Cable

  • No changes.

Active Storage

  • No changes.

Railties

  • No changes.

v6.0.4.7: 6.0.4.7

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • No changes.

Action Pack

  • No changes.

Active Job

  • No changes.

Action Mailer

  • No changes.

Action Cable

  • No changes.

Active Storage

  • Added image transformation validation via configurable allow-list.

    Variant now offers a configurable allow-list for transformation methods in addition to a configurable deny-list for arguments.

    [CVE-2022-21831]

Action Mailbox

  • No changes.

Action Text

  • No changes.

Railties

  • No changes.

v6.0.4.6: 6.0.4.6

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • No changes.

Action Pack

  • Fix Reloader method signature to work with the new Executor signature

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.

v6.0.4.5: 6.0.4.5

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • No changes.

Action Pack

  • Under certain circumstances, the middleware isn't informed that the response body has been fully closed which result in request state not being fully reset before the next request

    [CVE-2022-23633]

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.

v6.0.4.4: 6.0.4.4

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • No changes.

Action Pack

  • Fix issue with host protection not allowing host with port in development.

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.

v6.0.4.3: 6.0.4.3

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • No changes.

Action Pack

  • Fix issue with host protection not allowing localhost in development.

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

  • Allow localhost with a port by default in development

    [Fixes: #​43864]

v6.0.4.2: 6.0.4.2

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • No changes.

Action Pack

  • Fix X_FORWARDED_HOST protection. [CVE-2021-44528]

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.

v6.0.4.1

Compare Source

v6.0.4: 6.0.4

Compare Source

Active Support

  • Fixed issue in ActiveSupport::Cache::RedisCacheStore not passing options to read_multi causing fetch_multi to not work properly.

    Rajesh Sharma

  • with_options copies its options hash again to avoid leaking mutations.

    Fixes #​39343.

    Eugene Kenny

Active Model

  • No changes.

Active Record

  • Only warn about negative enums if a positive form that would cause conflicts exists.

    Fixes #​39065.

    Alex Ghiculescu

  • Allow the inverse of a has_one association that was previously autosaved to be loaded.

    Fixes #​34255.

    Steven Weber

  • Reset statement cache for association if table_name is changed.

    Fixes #​36453.

    Ryuta Kamizono

  • Type cast extra select for eager loading.

    Ryuta Kamizono

  • Prevent collection associations from being autosaved multiple times.

    Fixes #​39173.

    Eugene Kenny

  • Resolve issue with insert_all unique_by option when used with expression index.

    When the :unique_by option of ActiveRecord::Persistence.insert_all and ActiveRecord::Persistence.upsert_all was used with the name of an expression index, an error was raised. Adding a guard around the formatting behavior for the :unique_by corrects this.

    Usage:

    create_table :books, id: :integer, force: true do |t|
      t.column :name, :string
      t.index "lower(name)", unique: true
    end
    
    Book.insert_all [{ name: "MyTest" }], unique_by: :index_books_on_lower_name

    Fixes #​39516.

    Austen Madden

  • Fix preloading for polymorphic association with custom scope.

    Ryuta Kamizono

  • Allow relations with different SQL comments in the or method.

    Takumi Shotoku

  • Resolve conflict between counter cache and optimistic locking.

    Bump an Active Record instance's lock version after updating its counter cache. This avoids raising an unnecessary ActiveRecord::StaleObjectError upon subsequent transactions by maintaining parity with the corresponding database record's lock_version column.

    Fixes #​16449.

    Aaron Lipman

  • Fix through association with source/through scope which has joins.

    Ryuta Kamizono

  • Fix through association to respect source scope for includes/preload.

    Ryuta Kamizono

  • Fix eager load with Arel joins to maintain the original joins order.

    Ryuta Kamizono

  • Fix group by count with eager loading + order + limit/offset.

    Ryuta Kamizono

  • Fix left joins order when merging multiple left joins from different associations.

    Ryuta Kamizono

  • Fix index creation to preserve index comment in bulk change table on MySQL.

    Ryuta Kamizono

  • Change remove_foreign_key to not check :validate option if database doesn't support the feature.

    Ryuta Kamizono

  • Fix the result of aggregations to maintain duplicated "group by" fields.

    Ryuta Kamizono

  • Do not return duplicated records when using preload.

    Bogdan Gusiev

Action View

  • SanitizeHelper.sanitized_allowed_attributes and SanitizeHelper.sanitized_allowed_tags call safe_list_sanitizer's class method

    Fixes #​39586

    Taufiq Muhammadi

Action Pack

  • Accept base64_urlsafe CSRF tokens to make forward compatible.

    Base64 strict-encoded CSRF tokens are not inherently websafe, which makes them difficult to deal with. For example, the common practice of sending the CSRF token to a browser in a client-readable cookie does not work properly out of the box: the value has to be url-encoded and decoded to survive transport.

    In Rails 6.1, we generate Base64 urlsafe-encoded CSRF tokens, which are inherently safe to transport. Validation accepts both urlsafe tokens, and strict-encoded tokens for backwards compatibility.

    In Rails 5.2.5, the CSRF token format is accidentally changed to urlsafe-encoded. If you upgrade apps from 5.2.5, set the config urlsafe_csrf_tokens = true.

    Rails.application.config.action_controller.urlsafe_csrf_tokens = true

    Scott Blum, Étienne Barrié

  • Signed and encrypted cookies can now store false as their value when action_dispatch.use_cookies_with_metadata is enabled.

    Rolandas Barysas

Active Job

  • No changes.

Action Mailer

  • No changes.

Action Cable

  • No changes.

Active Storage

  • The Poppler PDF previewer renders a preview image using the original document's crop box rather than its media box, hiding print margins. This matches the behavior of the MuPDF previewer.

    Vincent Robert

Action Mailbox

  • No changes.

Action Text

  • No changes.

Railties

  • Allow relative paths with trailing slashes to be passed to rails test.

    Eugene Kenny

  • Return a 405 Method Not Allowed response when a request uses an unknown HTTP method.

    Fixes #​38998.

    Loren Norman

v6.0.3.7: 6.0.3.7

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • No changes.

Action Pack

  • Prevent catastrophic backtracking during mime parsing CVE-2021-22902

  • Prevent regex DoS in HTTP token authentication CVE-2021-22904

  • Prevent string polymorphic route arguments.

    url_for supports building polymorphic URLs via an array of arguments (usually symbols and records). If a developer passes a user input array, strings can result in unwanted route helper calls.

    CVE-2021-22885

    Gannon McGibbon

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.

v6.0.3.6: 6.0.3.6

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • No changes.

Action Pack

  • No changes.

Active Job

  • No changes.

Action Mailer

  • No changes.

Action Cable

  • No changes.

Active Storage

  • Marcel is upgraded to version 1.0.0 to avoid a dependency on GPL-licensed mime types data.

    George Claghorn

Action Mailbox

  • No changes.

Action Text

  • No changes.

Railties

  • No changes.

v6.0.3.5: 6.0.3.5

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • Fix possible DoS vector in PostgreSQL money type

    Carefully crafted input can cause a DoS via the regular expressions used for validating the money format in the PostgreSQL adapter. This patch fixes the regexp.

    Thanks to @​dee-see from Hackerone for this patch!

    [CVE-2021-22880]

    Aaron Patterson

Action View

  • No changes.

Action Pack

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.

v6.0.3.4: 6.0.3.4

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • No changes.

Action Pack

  • [CVE-2020-8264] Prevent XSS in Actionable Exceptions

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.

v6.0.3.3: 6.0.3.3

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • [CVE-2020-8185] Fix potential XSS vulnerability in the translate/t helper.

Action Pack

  • No changes.

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.

v6.0.3.2: 6.0.3.2

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • No changes.

Action Pack

  • [CVE-2020-8185] Only allow ActionableErrors if show_detailed_exceptions is enabled

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.

v6.0.3.1: 6.0.3.1

Compare Source

Active Support

  • [CVE-2020-8165] Deprecate Marshal.load on raw cache read in RedisCacheStore

  • [CVE-2020-8165] Avoid Marshal.load on raw cache value in MemCacheStore

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • [CVE-2020-8167] Check that request is same-origin prior to including CSRF token in XHRs

Action Pack

  • [CVE-2020-8166] HMAC raw CSRF token before masking it, so it cannot be used to reconstruct a per-form token

  • [CVE-2020-8164] Return self when calling #each, #each_pair, and #each_value instead of the raw @​parameters hash

Active Job

  • No changes.

Action Mailer

  • No changes.

Action Cable

  • No changes.

Active Storage

  • [CVE-2020-8162] Include Content-Length in signature for ActiveStorage direct upload

Action Mailbox

  • No changes.

Action Text

  • No changes.

Railties

  • No changes.

v6.0.3: 6.0.3

Compare Source

In this version, we fixed warnings when used with Ruby 2.7 across the entire framework.

Following are the list of other changes, per-framework.

Active Support

  • Array#to_sentence no longer returns a frozen string.

    Before:

    ['one', 'two'].to_sentence.frozen?

=> true

After:

    ['one', 'two'].to_sentence.frozen?

=> false

*Nicolas Dular*
  • Update ActiveSupport::Messages::Metadata#fresh? to work for cookies with expiry set when ActiveSupport.parse_json_times = true.

    Christian Gregg

Active Model

  • No changes.

Active Record

  • Recommend applications don't use the database kwarg in connected_to

    The database kwarg in connected_to was meant to be used for one-off scripts but is often used in requests. This is really dangerous because it re-establishes a connection every time. It's deprecated in 6.1 and will be removed in 6.2 without replacement. This change soft deprecates it in 6.0 by removing documentation.

    Eileen M. Uchitelle

  • Fix support for PostgreSQL 11+ partitioned indexes.

    Sebastián Palma

  • Add support for beginless ranges, introduced in Ruby 2.7.

    Josh Goodall

  • Fix insert_all with enum values

    Fixes #​38716.

    Joel Blum

  • Regexp-escape table name for MS SQL

    Add Regexp.escape to one method in ActiveRecord, so that table names with regular expression characters in them work as expected. Since MS SQL Server uses "[" and "]" to quote table and column names, and those characters are regular expression characters, methods like pluck and select fail in certain cases when used with the MS SQL Server adapter.

    Larry Reid

  • Store advisory locks on their own named connection.

    Previously advisory locks were taken out against a connection when a migration started. This works fine in single database applications but doesn't work well when migrations need to open new connections which results in the lock getting dropped.

    In order to fix this we are storing the advisory lock on a new connection with the connection specification name AdisoryLockBase. The caveat is that we need to maintain at least 2 connections to a database while migrations are running in order to do this.

    Eileen M. Uchitelle, John Crepezzi

  • Ensure :reading connections always raise if a write is attempted.

    Now Rails will raise an ActiveRecord::ReadOnlyError if any connection on the reading handler attempts to make a write. If your reading role needs to write you should name the role something other than :reading.

    Eileen M. Uchitelle

  • Enforce fresh ETag header after a collection's contents change by adding ActiveRecord::Relation#cache_key_with_version. This method will be used by ActionController::ConditionalGet to ensure that when collection cache versioning is enabled, requests using ConditionalGet don't return the same ETag header after a collection is modified. Fixes #​38078.

    Aaron Lipman

  • A database URL can now contain a querystring value that contains an equal sign. This is needed to support passing PostgresSQL options.

    Joshua Flanagan

  • Retain explicit selections on the base model after applying includes and joins.

    Resolves #​34889.

    Patrick Rebsch

Action View

  • annotated_source_code returns an empty array so TemplateErrors without a template in the backtrace are surfaced properly by DebugExceptions.

    Guilherme Mansur, Kasper Timm Hansen

  • Add autoload for SyntaxErrorInTemplate so syntax errors are correctly raised by DebugExceptions.

    Guilherme Mansur, Gannon McGibbon

Action Pack

  • Include child session assertion count in ActionDispatch::IntegrationTest

    IntegrationTest#open_session uses dup to create the new session, which meant it had its own copy of @assertions. This prevented the assertions from being correctly counted and reported.

    Child sessions now have their attr_accessor overriden to delegate to the root session.

    Fixes #​32142

    Sam Bostock

Active Job

  • While using perform_enqueued_jobs test helper enqueued jobs must be stored for the later check with assert_enqueued_with.

    Dmitry Polushkin

  • Add queue name support to Que adapter

    Brad Nauta, Wojciech Wnętrzak

Action Mailer

  • No changes.

Action Cable

  • No changes.

Active Storage

  • No changes.

Action Mailbox

  • Update Mandrill inbound email route to respond appropriately to HEAD requests for URL health checks from Mandrill.

    Bill Cromie

Action Text

  • No changes.

Railties

  • Cache compiled view templates when running tests by default

    When generating a new app without --skip-spring, caching classes is disabled in environments/test.rb. This implicitly disables caching view templates too. This change will enable view template caching by adding this to the generated environments/test.rb:

    config.action_view.cache_template_loading = true

    Jorge Manrubia

  • Rails::Application#eager_load! is available again to load application code manually as it was possible in previous versions.

    Please, note this is not integrated with the whole eager loading logic that runs when Rails boots with eager loading enabled, you can think of this method as a vanilla recursive code loader.

    This ability has been restored because there are some use cases for it, such as indexers that need to have all application classes and modules in memory.

    Xavier Noria

  • Generators that inherit from NamedBase respect --force option

    Josh Brody

  • Regression fix: The Rake task zeitwerk:check supports eager loaded namespaces which do not have eager load paths, like the recently added i18n. These namespaces are only required to respond to eager_load!.

    Xavier Noria

v6.0.2.2: 6.0.2.2

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • Fix possible XSS vector in escape_javascript helper

    CVE-2020-5267

    Aaron Patterson

Action Pack

  • No changes.

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.

v6.0.2.1: 6.0.2.1

Compare Source

Active Support

  • No changes.

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • No changes.

Action Pack

  • Fix possible information leak / session hijacking vulnerability.

    The ActionDispatch::Session::MemcacheStore is still vulnerable given it requires the gem dalli to be updated as well.

    CVE-2019-16782.

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.

v6.0.2: 6.0.2

Compare Source

Active Support

  • Eager load translations during initialization.

    Diego Plentz

  • Use per-thread CPU time clock on ActiveSupport::Notifications.

    George Claghorn

Active Model

  • No changes.

Active Record

  • Share the same connection pool for primary and replica databases in the transactional tests for the same database.

    Edouard Chin

  • Fix the preloader when one record is fetched using after_initialize but not the entire collection.

    Bradley Price

  • Fix collection callbacks not terminating when :abort is thrown.

    Edouard Chin, Ryuta Kamizono

  • Correctly deprecate where.not working as NOR for relations.

    12a9664 deprecated where.not working as NOR, however doing a relation query like where.not(relation: { ... }) wouldn't be properly deprecated and where.not would work as NAND instead.

    Edouard Chin

  • Fix db:migrate task with multiple databases to restore the connection to the previous database.

    The migrate task iterates and establish a connection over each db resulting in the last one to be used by subsequent rake tasks. We should reestablish a connection to the connection that was established before the migrate tasks was run

    Edouard Chin

  • Fix multi-threaded issue for AcceptanceValidator.

    Ryuta Kamizono

Action View

  • No changes.

Action Pack

  • Allow using mountable engine route helpers in System Tests.

    Chalo Fernandez

Active Job

Action Mailer

  • Fix ActionMailer assertions don't work for parameterized mail with legacy delivery job.

    bogdanvlviv

Action Cable

  • No changes.

Active Storage

  • No changes.

Action Mailbox

  • No changes.

Action Text

  • No changes.

Railties

  • Fix the collision check for the scaffold generator.

    Ryan Robeson

v6.0.1: 6.0.1

Compare Source

Active Support

  • ActiveSupport::SafeBuffer supports Enumerator methods.

    Shugo Maeda

  • The Redis cache store fails gracefully when the server returns a "max number of clients reached" error.

    Brandon Medenwald

  • Fixed that mutating a value returned by a memory cache store would unexpectedly change the cached value.

    Jonathan Hyman

  • The default inflectors in zeitwerk mode support overrides:

config/initializers/zeitwerk.rb

Rails.autoloaders.each do |autoloader|
  autoloader.inflector.inflect(
    "html_parser" => "HTMLParser",
    "ssl_error"   => "SSLError"
  )
end
```

That way, you can tweak how individual basenames are inflected without touching Active Support inflection rules, which are global. These inflectors fallback to `String#camelize`, so existing inflection rules are still taken into account for non-overridden basenames.

Please, check the [autoloading guide for `zeitwerk` mode](https://guides.rubyonrails.org/v6.0/autoloading_and_reloading_constants.html#customizing-inflections) if you prefer not to depend on `String#camelize` at all.

*Xavier Noria*
  • Improve Range#===, Range#include?, and Range#cover? to work with beginless (startless) and endless range targets.

    Allen Hsu, Andrew Hodgkinson

  • Don't use Process#clock_gettime(CLOCK_PROCESS_CPUTIME_ID) on Solaris

    Iain Beeston

Active Model

  • No changes.

Active Record

  • Common Table Expressions are allowed on read-only connections.

    Chris Morris

  • New record instantiation respects unscope.

    Ryuta Kamizono

  • Fixed a case where find_in_batches could halt too early.

    Takayuki Nakata

  • Autosaved associations always perform validations when a custom validation context is used.

    Tekin Suleyman

  • sql.active_record notifications now include the :connection in their payloads.

    Eugene Kenny

  • A rollback encountered in an after_commit callback does not reset previously-committed record state.

    Ryuta Kamizono

  • Fixed that join order was lost when eager-loading.

    Ryuta Kamizono

  • DESCRIBE queries are allowed on read-only connections.

    Dylan Thacker-Smith

  • Fixed that records that had been inspected could not be marshaled.

    Eugene Kenny

  • The connection pool reaper thread is respawned in forked processes. This fixes that idle connections in forked processes wouldn't be reaped.

    John Hawthorn

  • The memoized result of ActiveRecord::Relation#take is properly cleared when ActiveRecord::Relation#reset or ActiveRecord::Relation#reload is called.

    Anmol Arora

  • Fixed the performance regression for primary_keys introduced MySQL 8.0.

    Hiroyuki Ishii

  • insert, insert_all, upsert, and upsert_all now clear the query cache.

    Eugene Kenny

  • Call while_preventing_writes directly from connected_to.

    In some cases application authors want to use the database switching middleware and make explicit calls with connected_to. It's possible for an app to turn off writes and not turn them back on by the time we call connected_to(role: :writing).

    This change allows apps to fix this by assuming if a role is writing we want to allow writes, except in the case it's explicitly turned off.

    Eileen M. Uchitelle

  • Improve detection of ActiveRecord::StatementTimeout with mysql2 adapter in the edge case when the query is terminated during filesort.

    Kir Shatrov

Action View

  • UJS avoids Element.closest() for IE 9 compatibility.

    George Claghorn

Action Pack

  • ActionDispatch::SystemTestCase now inherits from ActiveSupport::TestCase rather than ActionDispatch::IntegrationTest. This permits running jobs in system tests.

    George Claghorn, Edouard Chin

  • Registered MIME types may contain extra flags:

    Mime::Type.register "text/html; fragment", :html_fragment

    Aaron Patterson

Active Job

  • No changes.

Action Mailer

  • No changes.

Action Cable

  • No changes.

Active Storage

  • ActiveStorage::AnalyzeJobs are discarded on ActiveRecord::RecordNotFound errors.

    George Claghorn

  • Blobs are recorded in the database before being uploaded to the service. This fixes that generated blob keys could silently collide, leading to data loss.

    Julik Tarkhanov

Action Mailbox

  • No changes.

Action Text

  • No changes.

Railties

  • The zeitwerk:check Rake task reports files outside the app's root directory, as in engines loaded from gems.

    Xavier Noria

  • Fixed a possible error when using the evented file update checker.

    Yuji Yaginuma

  • The sqlite3 database files created by the parallel testing feature are included in the default .gitignore file for newly-generated apps.

    Yasuo Honda

  • rails new generates a .keep file in tmp/pids. This fixes starting a server via rackup instead of rails server.

    Rafael Mendonça França

v6.0.0

Compare Source


Configuration

📅 Schedule: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 Automerge: Enabled.

Rebasing: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this MR and you won't be reminded about this update again.


  • If you want to rebase/retry this MR, check this box

This MR has been generated by Renovate Bot.

Merge request reports