* Add `TimeZoneConverter#==` method, so objects will be properly compared by their type, scale, limit & precision. Address #52699. *Ruy Rocha* * Add support for SQLite3 full-text-search and other virtual tables. Previously, adding sqlite3 virtual tables messed up `schema.rb`. Now, virtual tables can safely be added using `create_virtual_table`. *Zacharias Knudsen* * Support use of alternative database interfaces via the `database_cli` ActiveRecord configuration option. ```ruby Rails.application.configure do config.active_record.database_cli = { postgresql: "pgcli" } end ``` *T S Vallender* * Add support for dumping table inheritance and native partitioning table definitions for PostgeSQL adapter *Justin Talbott* * Infer default `:inverse_of` option for `delegated_type` definitions. ```ruby class Entry < ApplicationRecord delegated_type :entryable, types: %w[ Message ] # => defaults to inverse_of: :entry end ``` *Sean Doyle* * Add support for `ActiveRecord::Point` type casts using `Hash` values This allows `ActiveRecord::Point` to be cast or serialized from a hash with `:x` and `:y` keys of numeric values, mirroring the functionality of existing casts for string and array values. Both string and symbol keys are supported. ```ruby class PostgresqlPoint < ActiveRecord::Base attribute :x, :point attribute :y, :point attribute :z, :point end val = PostgresqlPoint.new({ x: '(12.34, -43.21)', y: [12.34, '-43.21'], z: {x: '12.34', y: -43.21} }) ActiveRecord::Point.new(12.32, -43.21) == val.x == val.y == val.z ``` *Stephen Drew* * Replace `SQLite3::Database#busy_timeout` with `#busy_handler_timeout=`. Provides a non-GVL-blocking, fair retry interval busy handler implementation. *Stephen Margheim* * SQLite3Adapter: Translate `SQLite3::BusyException` into `ActiveRecord::StatementTimeout`. *Matthew Nguyen* * Include schema name in `enable_extension` statements in `db/schema.rb`. The schema dumper will now include the schema name in generated `enable_extension` statements if they differ from the current schema. For example, if you have a migration: ```ruby enable_extension "heroku_ext.pgcrypto" enable_extension "pg_stat_statements" ``` then the generated schema dump will also contain: ```ruby enable_extension "heroku_ext.pgcrypto" enable_extension "pg_stat_statements" ``` *Tony Novak* * Fix `ActiveRecord::Encryption::EncryptedAttributeType#type` to return actual cast type. *Vasiliy Ermolovich* * SQLite3Adapter: Bulk insert fixtures. Previously one insert command was executed for each fixture, now they are aggregated in a single bulk insert command. *Lázaro Nixon* * PostgreSQLAdapter: Allow `disable_extension` to be called with schema-qualified name. For parity with `enable_extension`, the `disable_extension` method can be called with a schema-qualified name (e.g. `disable_extension "myschema.pgcrypto"`). Note that PostgreSQL's `DROP EXTENSION` does not actually take a schema name (unlike `CREATE EXTENSION`), so the resulting SQL statement will only name the extension, e.g. `DROP EXTENSION IF EXISTS "pgcrypto"`. *Tony Novak* * Make `create_schema` / `drop_schema` reversible in migrations. Previously, `create_schema` and `drop_schema` were irreversible migration operations. *Tony Novak* * Support batching using custom columns. ```ruby Product.in_batches(cursor: [:shop_id, :id]) do |relation| # do something with relation end ``` *fatkodima* * Use SQLite `IMMEDIATE` transactions when possible. Transactions run against the SQLite3 adapter default to IMMEDIATE mode to improve concurrency support and avoid busy exceptions. *Stephen Margheim* * Raise specific exception when a connection is not defined. The new `ConnectionNotDefined` exception provides connection name, shard and role accessors indicating the details of the connection that was requested. *Hana Harencarova*, *Matthew Draper* * Delete the deprecated constant `ActiveRecord::ImmutableRelation`. *Xavier Noria* * Fix duplicate callback execution when child autosaves parent with `has_one` and `belongs_to`. Before, persisting a new child record with a new associated parent record would run `before_validation`, `after_validation`, `before_save` and `after_save` callbacks twice. Now, these callbacks are only executed once as expected. *Joshua Young* * `ActiveRecord::Encryption::Encryptor` now supports a `:compressor` option to customize the compression algorithm used. ```ruby module ZstdCompressor def self.deflate(data) Zstd.compress(data) end def self.inflate(data) Zstd.decompress(data) end end class User encrypts :name, compressor: ZstdCompressor end ``` You disable compression by passing `compress: false`. ```ruby class User encrypts :name, compress: false end ``` *heka1024* * Add condensed `#inspect` for `ConnectionPool`, `AbstractAdapter`, and `DatabaseConfig`. *Hartley McGuire* * Add `.shard_keys`, `.sharded?`, & `.connected_to_all_shards` methods. ```ruby class ShardedBase < ActiveRecord::Base self.abstract_class = true connects_to shards: { shard_one: { writing: :shard_one }, shard_two: { writing: :shard_two } } end class ShardedModel < ShardedBase end ShardedModel.shard_keys => [:shard_one, :shard_two] ShardedModel.sharded? => true ShardedBase.connected_to_all_shards { ShardedModel.current_shard } => [:shard_one, :shard_two] ``` *Nony Dutton* * Add a `filter` option to `in_order_of` to prioritize certain values in the sorting without filtering the results by these values. *Igor Depolli* * Fix an issue where the IDs reader method did not return expected results for preloaded associations in models using composite primary keys. *Jay Ang* * Allow to configure `strict_loading_mode` globally or within a model. Defaults to `:all`, can be changed to `:n_plus_one_only`. *Garen Torikian* * Add `ActiveRecord::Relation#readonly?`. Reflects if the relation has been marked as readonly. *Theodor Tonum* * Improve `ActiveRecord::Store` to raise a descriptive exception if the column is not either structured (e.g., PostgreSQL +hstore+/+json+, or MySQL +json+) or declared serializable via `ActiveRecord.store`. Previously, a `NoMethodError` would be raised when the accessor was read or written: NoMethodError: undefined method `accessor' for an instance of ActiveRecord::Type::Text Now, a descriptive `ConfigurationError` is raised: ActiveRecord::ConfigurationError: the column 'metadata' has not been configured as a store. Please make sure the column is declared serializable via 'ActiveRecord.store' or, if your database supports it, use a structured column type like hstore or json. *Mike Dalessio* * Fix inference of association model on nested models with the same demodularized name. E.g. with the following setup: ```ruby class Nested::Post < ApplicationRecord has_one :post, through: :other end ``` Before, `#post` would infer the model as `Nested::Post`, but now it correctly infers `Post`. *Joshua Young* * Add public method for checking if a table is ignored by the schema cache. Previously, an application would need to reimplement `ignored_table?` from the schema cache class to check if a table was set to be ignored. This adds a public method to support this and updates the schema cache to use that directly. ```ruby ActiveRecord.schema_cache_ignored_tables = ["developers"] ActiveRecord.schema_cache_ignored_table?("developers") => true ``` *Eileen M. Uchitelle* Please check [7-2-stable](https://github.com/rails/rails/blob/7-2-stable/activerecord/CHANGELOG.md) for previous changes.