rails/activerecord/CHANGELOG.md

278 lines
8.1 KiB
Markdown
Raw Normal View History

* 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*
2024-08-17 15:21:46 +08:00
* Replace `SQLite3::Database#busy_timeout` with `#busy_handler_timeout=`.
2024-08-17 15:21:46 +08:00
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*
2024-08-11 15:05:44 +08:00
* 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*
2024-07-13 22:19:06 +08:00
* 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` & `.connected_to_all_shards` Currently, there is no (simple) way to ask a model if it connects to a single database or to multiple shards. Furthermore, without looping through a model's connections, I don't believe there's an easy way to return a list of shards a model can connect to. This commit adds a `@shard_keys` ivar that's set whenever `.connects_to` is called. It sets the ivar to the result of `shards.keys`. `shards` in `.connects_to` defaults to an empty hash and therefore when calling `connects_to database: {...}` `@shard_keys` will be set to an empty array. `@shard_keys` is set _before_ the following lines: ``` if shards.empty? shards[:default] = database end ``` This conditional sets the one and only shard (`:default`) to the value of `database` that we pass to `.connects_to`. This allows for calling `connected_to(shard: :default)` on models configured to only connect to a database e.g.: ```ruby class UnshardedBase < ActiveRecord::Base self.abstract_class = true connects_to database: { writing: :primary } end class UnshardedModel < UnshardedBase end UnshardedBase.connected_to(shard: :default) { UnshardedBase.connection_pool.db_config.name } => primary ``` This is ultimately still an _unsharded_ model which is why `@shard_keys` gets set before the conditional. With the new `@shard_keys` ivar we need a way for descendants of the abstract AR model to return that same value. For that we leverage the existing `.connection_class_for_self` method. That method returns the ancestor of the model where `.connects_to` was called, or returns self if it's the connection class: ```ruby class UnshardedBase < ActiveRecord::Base self.abstract_class = true connects_to database: { writing: :primary } end class UnshardedModel < UnshardedBase end ActiveRecord::Base.connection_class_for_self => ActiveRecord::Base UnshardedBase.connection_class_for_self => UnshardedBase(abstract) UnshardedModel.connection_class_for_self => UnshardedBase(abstract) ``` The new `.shard_keys` method is a getter which returns the value of `@shard_keys` from the connection class or it returns an empty array. The empty array is necessary in cases where `connects_to` was never called. Finally, I've added an `.connected_to_all_shards` method which takes all of the arguments for `.connected_to` except for `shard`. Instead, it loops through every shard key and then delegates everything else to `.connected_to`. I've used `.map` instead of `.each` so that we can collect the results of each block.
2024-02-08 16:05:22 +08:00
* 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.