activerecord 7.2.2.1 → 8.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +564 -753
- data/README.rdoc +2 -2
- data/lib/active_record/association_relation.rb +2 -1
- data/lib/active_record/associations/alias_tracker.rb +6 -4
- data/lib/active_record/associations/association.rb +35 -11
- data/lib/active_record/associations/belongs_to_association.rb +18 -2
- data/lib/active_record/associations/builder/association.rb +23 -11
- data/lib/active_record/associations/builder/belongs_to.rb +17 -4
- data/lib/active_record/associations/builder/collection_association.rb +7 -3
- data/lib/active_record/associations/builder/has_one.rb +1 -1
- data/lib/active_record/associations/builder/singular_association.rb +33 -5
- data/lib/active_record/associations/collection_association.rb +10 -8
- data/lib/active_record/associations/collection_proxy.rb +22 -4
- data/lib/active_record/associations/deprecation.rb +88 -0
- data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
- data/lib/active_record/associations/errors.rb +3 -0
- data/lib/active_record/associations/has_many_through_association.rb +3 -2
- data/lib/active_record/associations/join_dependency/join_association.rb +25 -27
- data/lib/active_record/associations/join_dependency.rb +4 -2
- data/lib/active_record/associations/preloader/association.rb +2 -2
- data/lib/active_record/associations/preloader/batch.rb +7 -1
- data/lib/active_record/associations/preloader/branch.rb +1 -0
- data/lib/active_record/associations/singular_association.rb +8 -3
- data/lib/active_record/associations.rb +192 -24
- data/lib/active_record/asynchronous_queries_tracker.rb +28 -24
- data/lib/active_record/attribute_methods/primary_key.rb +4 -8
- data/lib/active_record/attribute_methods/query.rb +34 -0
- data/lib/active_record/attribute_methods/serialization.rb +17 -4
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -14
- data/lib/active_record/attribute_methods.rb +24 -19
- data/lib/active_record/attributes.rb +40 -26
- data/lib/active_record/autosave_association.rb +91 -39
- data/lib/active_record/base.rb +3 -4
- data/lib/active_record/coders/json.rb +14 -5
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +35 -28
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +16 -4
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +51 -13
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +458 -117
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +136 -74
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +44 -11
- data/lib/active_record/connection_adapters/abstract/quoting.rb +16 -25
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +11 -7
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +37 -36
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +122 -29
- data/lib/active_record/connection_adapters/abstract/transaction.rb +40 -8
- data/lib/active_record/connection_adapters/abstract_adapter.rb +175 -87
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +77 -58
- data/lib/active_record/connection_adapters/column.rb +17 -4
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +4 -4
- data/lib/active_record/connection_adapters/mysql/quoting.rb +7 -9
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +41 -10
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +73 -46
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +89 -94
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +10 -11
- data/lib/active_record/connection_adapters/pool_config.rb +7 -7
- data/lib/active_record/connection_adapters/postgresql/column.rb +4 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +76 -45
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +10 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +21 -10
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -4
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +9 -17
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +28 -45
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +69 -32
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +140 -64
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +83 -105
- data/lib/active_record/connection_adapters/schema_cache.rb +3 -5
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +90 -98
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +13 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +0 -6
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +27 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +13 -13
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +112 -42
- data/lib/active_record/connection_adapters/statement_pool.rb +4 -2
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +38 -67
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +2 -19
- data/lib/active_record/connection_adapters.rb +1 -56
- data/lib/active_record/connection_handling.rb +37 -10
- data/lib/active_record/core.rb +61 -25
- data/lib/active_record/counter_cache.rb +34 -9
- data/lib/active_record/database_configurations/connection_url_resolver.rb +3 -1
- data/lib/active_record/database_configurations/database_config.rb +9 -1
- data/lib/active_record/database_configurations/hash_config.rb +67 -9
- data/lib/active_record/database_configurations/url_config.rb +13 -3
- data/lib/active_record/database_configurations.rb +7 -3
- data/lib/active_record/delegated_type.rb +19 -19
- data/lib/active_record/dynamic_matchers.rb +54 -69
- data/lib/active_record/encryption/config.rb +3 -1
- data/lib/active_record/encryption/encryptable_record.rb +9 -9
- data/lib/active_record/encryption/encrypted_attribute_type.rb +12 -3
- data/lib/active_record/encryption/encryptor.rb +49 -28
- data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -2
- data/lib/active_record/encryption/scheme.rb +9 -2
- data/lib/active_record/enum.rb +46 -42
- data/lib/active_record/errors.rb +36 -12
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/explain_registry.rb +51 -2
- data/lib/active_record/filter_attribute_handler.rb +73 -0
- data/lib/active_record/fixture_set/table_row.rb +19 -2
- data/lib/active_record/fixtures.rb +2 -4
- data/lib/active_record/future_result.rb +13 -9
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +1 -1
- data/lib/active_record/insert_all.rb +12 -7
- data/lib/active_record/locking/optimistic.rb +8 -1
- data/lib/active_record/locking/pessimistic.rb +5 -0
- data/lib/active_record/log_subscriber.rb +3 -13
- data/lib/active_record/middleware/shard_selector.rb +34 -17
- data/lib/active_record/migration/command_recorder.rb +44 -11
- data/lib/active_record/migration/compatibility.rb +37 -24
- data/lib/active_record/migration/default_schema_versions_formatter.rb +30 -0
- data/lib/active_record/migration.rb +50 -43
- data/lib/active_record/model_schema.rb +38 -13
- data/lib/active_record/nested_attributes.rb +6 -6
- data/lib/active_record/persistence.rb +162 -133
- data/lib/active_record/query_cache.rb +22 -15
- data/lib/active_record/query_logs.rb +104 -52
- data/lib/active_record/query_logs_formatter.rb +17 -28
- data/lib/active_record/querying.rb +12 -12
- data/lib/active_record/railtie.rb +37 -32
- data/lib/active_record/railties/controller_runtime.rb +11 -6
- data/lib/active_record/railties/databases.rake +26 -37
- data/lib/active_record/railties/job_checkpoints.rb +15 -0
- data/lib/active_record/railties/job_runtime.rb +10 -11
- data/lib/active_record/reflection.rb +53 -21
- data/lib/active_record/relation/batches/batch_enumerator.rb +4 -3
- data/lib/active_record/relation/batches.rb +147 -73
- data/lib/active_record/relation/calculations.rb +80 -63
- data/lib/active_record/relation/delegation.rb +25 -15
- data/lib/active_record/relation/finder_methods.rb +54 -37
- data/lib/active_record/relation/merger.rb +8 -8
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +11 -9
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +8 -8
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +4 -3
- data/lib/active_record/relation/predicate_builder.rb +22 -7
- data/lib/active_record/relation/query_attribute.rb +4 -2
- data/lib/active_record/relation/query_methods.rb +156 -95
- data/lib/active_record/relation/spawn_methods.rb +7 -7
- data/lib/active_record/relation/where_clause.rb +10 -11
- data/lib/active_record/relation.rb +122 -80
- data/lib/active_record/result.rb +109 -24
- data/lib/active_record/runtime_registry.rb +42 -58
- data/lib/active_record/sanitization.rb +9 -6
- data/lib/active_record/schema_dumper.rb +47 -22
- data/lib/active_record/schema_migration.rb +2 -1
- data/lib/active_record/scoping/named.rb +5 -2
- data/lib/active_record/scoping.rb +0 -1
- data/lib/active_record/secure_token.rb +3 -3
- data/lib/active_record/signed_id.rb +47 -18
- data/lib/active_record/statement_cache.rb +24 -20
- data/lib/active_record/store.rb +51 -22
- data/lib/active_record/structured_event_subscriber.rb +85 -0
- data/lib/active_record/table_metadata.rb +6 -23
- data/lib/active_record/tasks/abstract_tasks.rb +76 -0
- data/lib/active_record/tasks/database_tasks.rb +85 -85
- data/lib/active_record/tasks/mysql_database_tasks.rb +3 -42
- data/lib/active_record/tasks/postgresql_database_tasks.rb +14 -40
- data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -28
- data/lib/active_record/test_databases.rb +14 -4
- data/lib/active_record/test_fixtures.rb +39 -2
- data/lib/active_record/testing/query_assertions.rb +8 -2
- data/lib/active_record/timestamp.rb +4 -2
- data/lib/active_record/token_for.rb +1 -1
- data/lib/active_record/transaction.rb +2 -5
- data/lib/active_record/transactions.rb +39 -16
- data/lib/active_record/type/hash_lookup_type_map.rb +2 -1
- data/lib/active_record/type/internal/timezone.rb +7 -0
- data/lib/active_record/type/json.rb +15 -2
- data/lib/active_record/type/serialized.rb +11 -4
- data/lib/active_record/type/type_map.rb +1 -1
- data/lib/active_record/type_caster/connection.rb +2 -1
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record/validations/uniqueness.rb +8 -8
- data/lib/active_record.rb +85 -50
- data/lib/arel/alias_predication.rb +2 -0
- data/lib/arel/collectors/bind.rb +2 -2
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +2 -2
- data/lib/arel/crud.rb +8 -11
- data/lib/arel/delete_manager.rb +5 -0
- data/lib/arel/nodes/binary.rb +1 -1
- data/lib/arel/nodes/count.rb +2 -2
- data/lib/arel/nodes/delete_statement.rb +4 -2
- data/lib/arel/nodes/function.rb +4 -10
- data/lib/arel/nodes/named_function.rb +2 -2
- data/lib/arel/nodes/node.rb +2 -2
- data/lib/arel/nodes/sql_literal.rb +1 -1
- data/lib/arel/nodes/update_statement.rb +4 -2
- data/lib/arel/nodes.rb +0 -2
- data/lib/arel/select_manager.rb +13 -4
- data/lib/arel/table.rb +3 -7
- data/lib/arel/update_manager.rb +5 -0
- data/lib/arel/visitors/dot.rb +2 -3
- data/lib/arel/visitors/postgresql.rb +55 -0
- data/lib/arel/visitors/sqlite.rb +55 -8
- data/lib/arel/visitors/to_sql.rb +6 -22
- data/lib/arel.rb +3 -1
- data/lib/rails/generators/active_record/application_record/USAGE +1 -1
- metadata +17 -17
- data/lib/active_record/explain_subscriber.rb +0 -34
- data/lib/active_record/normalization.rb +0 -163
- data/lib/active_record/relation/record_fetch_warning.rb +0 -52
data/CHANGELOG.md
CHANGED
|
@@ -1,1098 +1,909 @@
|
|
|
1
|
-
## Rails
|
|
1
|
+
## Rails 8.1.2 (January 08, 2026) ##
|
|
2
2
|
|
|
3
|
-
*
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
## Rails 7.2.2 (October 30, 2024) ##
|
|
7
|
-
|
|
8
|
-
* Fix support for `query_cache: false` in `database.yml`.
|
|
9
|
-
|
|
10
|
-
`query_cache: false` would no longer entirely disable the Active Record query cache.
|
|
11
|
-
|
|
12
|
-
*zzak*
|
|
13
|
-
|
|
14
|
-
* Set `.attributes_for_inspect` to `:all` by default.
|
|
15
|
-
|
|
16
|
-
For new applications it is set to `[:id]` in config/environment/production.rb.
|
|
17
|
-
|
|
18
|
-
In the console all the attributes are always shown.
|
|
19
|
-
|
|
20
|
-
*Andrew Novoselac*
|
|
3
|
+
* Fix counting cached queries in `ActiveRecord::RuntimeRegistry`.
|
|
21
4
|
|
|
22
|
-
*
|
|
23
|
-
|
|
24
|
-
*Kazuma Watanabe*
|
|
25
|
-
|
|
26
|
-
* Fix marshalling of unsaved associated records in 7.1 format.
|
|
27
|
-
|
|
28
|
-
The 7.1 format would only marshal associated records if the association was loaded.
|
|
29
|
-
But associations that would only contain unsaved records would be skipped.
|
|
5
|
+
*fatkodima*
|
|
30
6
|
|
|
31
|
-
|
|
7
|
+
* Fix merging relations with arel equality predicates with null relations.
|
|
32
8
|
|
|
33
|
-
*
|
|
9
|
+
*fatkodima*
|
|
34
10
|
|
|
35
|
-
|
|
11
|
+
* Fix SQLite3 schema dump for non-autoincrement integer primary keys.
|
|
36
12
|
|
|
37
|
-
|
|
38
|
-
|
|
13
|
+
Previously, `schema.rb` should incorrectly restore that table with an auto incrementing
|
|
14
|
+
primary key.
|
|
39
15
|
|
|
40
|
-
*
|
|
16
|
+
*Chris Hasiński*
|
|
41
17
|
|
|
42
|
-
* Fix
|
|
18
|
+
* Fix PostgreSQL `schema_search_path` not being reapplied after `reset!` or `reconnect!`.
|
|
43
19
|
|
|
44
|
-
|
|
20
|
+
The `schema_search_path` configured in `database.yml` is now correctly
|
|
21
|
+
reapplied instead of falling back to PostgreSQL defaults.
|
|
45
22
|
|
|
46
|
-
*
|
|
23
|
+
*Tobias Egli*
|
|
47
24
|
|
|
48
|
-
|
|
25
|
+
* Restore the ability of enum to be foats.
|
|
49
26
|
|
|
50
27
|
```ruby
|
|
51
|
-
|
|
52
|
-
has_one :middle, dependent: :destroy
|
|
53
|
-
has_one :right, through: :middle
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
class Middle < ActiveRecord::Base
|
|
57
|
-
belongs_to :left, dependent: :destroy
|
|
58
|
-
belongs_to :right, dependent: :destroy
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
class Right < ActiveRecord::Base
|
|
62
|
-
has_one :middle, dependent: :destroy
|
|
63
|
-
has_one :left, through: :middle
|
|
64
|
-
end
|
|
28
|
+
enum :rating, { low: 0.0, medium: 0.5, high: 1.0 },
|
|
65
29
|
```
|
|
66
|
-
In the above example `left.destroy` wouldn't destroy its associated `Right`
|
|
67
|
-
record.
|
|
68
|
-
|
|
69
|
-
*Andy Stewart*
|
|
70
30
|
|
|
71
|
-
|
|
31
|
+
In Rails 8.1.0, enum values are eagerly validated, and floats weren't expected.
|
|
72
32
|
|
|
73
|
-
|
|
33
|
+
*Said Kaldybaev*
|
|
74
34
|
|
|
75
|
-
|
|
76
|
-
such as capybara, it could happen that a connection end up pinned by the
|
|
77
|
-
server thread rather than the test thread, causing
|
|
78
|
-
`"Cannot expire connection, it is owned by a different thread"` errors.
|
|
35
|
+
* Ensure batched preloaded associations accounts for klass when grouping to avoid issues with STI.
|
|
79
36
|
|
|
80
|
-
*
|
|
37
|
+
*zzak*, *Stjepan Hadjic*
|
|
81
38
|
|
|
82
|
-
* Fix `ActiveRecord::
|
|
39
|
+
* Fix `ActiveRecord::SoleRecordExceeded#record` to return the relation.
|
|
83
40
|
|
|
84
|
-
|
|
41
|
+
This was the case until Rails 7.2, but starting from 8.0 it
|
|
42
|
+
started mistakenly returning the model class.
|
|
85
43
|
|
|
86
|
-
|
|
87
|
-
User.with(foo: [User.select(:id), User.select(:id), User.select(:id)]).to_sql
|
|
88
|
-
undefined method `union' for an instance of Arel::Nodes::UnionAll (NoMethodError)
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
The above now works as expected.
|
|
44
|
+
*Jean Boussier*
|
|
92
45
|
|
|
93
|
-
|
|
46
|
+
* Improve PostgreSQLAdapter resilience to Timeout.timeout.
|
|
94
47
|
|
|
95
|
-
|
|
48
|
+
Better handle asynchronous exceptions being thrown inside
|
|
49
|
+
the `reconnect!` method.
|
|
96
50
|
|
|
97
|
-
|
|
51
|
+
This may fixes some deep errors such as:
|
|
98
52
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
53
|
+
```
|
|
54
|
+
undefined method `key?' for nil:NilClass (NoMethodError)
|
|
55
|
+
if !type_map.key?(oid)
|
|
56
|
+
```
|
|
102
57
|
|
|
103
58
|
*Jean Boussier*
|
|
104
59
|
|
|
105
|
-
*
|
|
60
|
+
* Fix structured events for Active Record was not being emitted.
|
|
106
61
|
|
|
107
|
-
|
|
62
|
+
*Yuji Yaginuma*
|
|
108
63
|
|
|
109
|
-
|
|
64
|
+
* Fix `eager_load` when loading `has_many` assocations with composite primary keys.
|
|
110
65
|
|
|
111
|
-
|
|
112
|
-
the same child association but different parents does not join all parents.
|
|
66
|
+
This would result in some records being loaded multiple times.
|
|
113
67
|
|
|
114
|
-
|
|
68
|
+
*Martin-Alexander*
|
|
115
69
|
|
|
116
|
-
Now it will correctly join both parents.
|
|
117
70
|
|
|
118
|
-
|
|
71
|
+
## Rails 8.1.1 (October 28, 2025) ##
|
|
119
72
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
* Ensure `ActiveRecord::Encryption.config` is always ready before access.
|
|
73
|
+
* No changes.
|
|
123
74
|
|
|
124
|
-
Previously, `ActiveRecord::Encryption` configuration was deferred until `ActiveRecord::Base`
|
|
125
|
-
was loaded. Therefore, accessing `ActiveRecord::Encryption.config` properties before
|
|
126
|
-
`ActiveRecord::Base` was loaded would give incorrect results.
|
|
127
75
|
|
|
128
|
-
|
|
129
|
-
soon as needed.
|
|
76
|
+
## Rails 8.1.0 (October 22, 2025) ##
|
|
130
77
|
|
|
131
|
-
|
|
132
|
-
`ActiveRecord::Encryption`, thus preserving the original behavior of having its config ready
|
|
133
|
-
before any use of `ActiveRecord::Base`.
|
|
78
|
+
* Fix SQLite3 data loss during table alterations with CASCADE foreign keys.
|
|
134
79
|
|
|
135
|
-
|
|
80
|
+
When altering a table in SQLite3 that is referenced by child tables with
|
|
81
|
+
`ON DELETE CASCADE` foreign keys, ActiveRecord would silently delete all
|
|
82
|
+
data from the child tables. This occurred because SQLite requires table
|
|
83
|
+
recreation for schema changes, and during this process the original table
|
|
84
|
+
is temporarily dropped, triggering CASCADE deletes on child tables.
|
|
136
85
|
|
|
137
|
-
|
|
138
|
-
|
|
86
|
+
The root cause was incorrect ordering of operations. The original code
|
|
87
|
+
wrapped `disable_referential_integrity` inside a transaction, but
|
|
88
|
+
`PRAGMA foreign_keys` cannot be modified inside a transaction in SQLite -
|
|
89
|
+
attempting to do so simply has no effect. This meant foreign keys remained
|
|
90
|
+
enabled during table recreation, causing CASCADE deletes to fire.
|
|
139
91
|
|
|
140
|
-
|
|
92
|
+
The fix reverses the order to follow the official SQLite 12-step ALTER TABLE
|
|
93
|
+
procedure: `disable_referential_integrity` now wraps the transaction instead
|
|
94
|
+
of being wrapped by it. This ensures foreign keys are properly disabled
|
|
95
|
+
before the transaction starts and re-enabled after it commits, preventing
|
|
96
|
+
CASCADE deletes while maintaining data integrity through atomic transactions.
|
|
141
97
|
|
|
142
98
|
*Ruy Rocha*
|
|
143
99
|
|
|
100
|
+
* Add replicas to test database parallelization setup.
|
|
144
101
|
|
|
145
|
-
|
|
102
|
+
Setup and configuration of databases for parallel testing now includes replicas.
|
|
146
103
|
|
|
147
|
-
|
|
104
|
+
This fixes an issue when using a replica database, database selector middleware,
|
|
105
|
+
and non-transactional tests, where integration tests running in parallel would select
|
|
106
|
+
the base test database, i.e. `db_test`, instead of the numbered parallel worker database,
|
|
107
|
+
i.e. `db_test_{n}`.
|
|
148
108
|
|
|
109
|
+
*Adam Maas*
|
|
149
110
|
|
|
150
|
-
|
|
111
|
+
* Support virtual (not persisted) generated columns on PostgreSQL 18+
|
|
151
112
|
|
|
152
|
-
|
|
113
|
+
PostgreSQL 18 introduces virtual (not persisted) generated columns,
|
|
114
|
+
which are now the default unless the `stored: true` option is explicitly specified on PostgreSQL 18+.
|
|
153
115
|
|
|
116
|
+
```ruby
|
|
117
|
+
create_table :users do |t|
|
|
118
|
+
t.string :name
|
|
119
|
+
t.virtual :lower_name, type: :string, as: "LOWER(name)", stored: false
|
|
120
|
+
t.virtual :name_length, type: :integer, as: "LENGTH(name)"
|
|
121
|
+
end
|
|
122
|
+
```
|
|
154
123
|
|
|
155
|
-
|
|
124
|
+
*Yasuo Honda*
|
|
156
125
|
|
|
157
|
-
*
|
|
126
|
+
* Optimize schema dumping to prevent duplicate file generation.
|
|
158
127
|
|
|
159
|
-
|
|
128
|
+
`ActiveRecord::Tasks::DatabaseTasks.dump_all` now tracks which schema files
|
|
129
|
+
have already been dumped and skips dumping the same file multiple times.
|
|
130
|
+
This improves performance when multiple database configurations share the
|
|
131
|
+
same schema dump path.
|
|
160
132
|
|
|
161
|
-
*
|
|
133
|
+
*Mikey Gough*, *Hartley McGuire*
|
|
162
134
|
|
|
163
|
-
|
|
135
|
+
* Add structured events for Active Record:
|
|
136
|
+
- `active_record.strict_loading_violation`
|
|
137
|
+
- `active_record.sql`
|
|
164
138
|
|
|
165
|
-
*
|
|
139
|
+
*Gannon McGibbon*
|
|
166
140
|
|
|
167
|
-
|
|
141
|
+
* Add support for integer shard keys.
|
|
142
|
+
```ruby
|
|
143
|
+
# Now accepts symbols as shard keys.
|
|
144
|
+
ActiveRecord::Base.connects_to(shards: {
|
|
145
|
+
1: { writing: :primary_shard_one, reading: :primary_shard_one },
|
|
146
|
+
2: { writing: :primary_shard_two, reading: :primary_shard_two},
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
ActiveRecord::Base.connected_to(shard: 1) do
|
|
150
|
+
# ..
|
|
151
|
+
end
|
|
152
|
+
```
|
|
168
153
|
|
|
169
|
-
*
|
|
154
|
+
*Nony Dutton*
|
|
170
155
|
|
|
171
|
-
|
|
156
|
+
* Add `ActiveRecord::Base.only_columns`
|
|
172
157
|
|
|
173
|
-
|
|
158
|
+
Similar in use case to `ignored_columns` but listing columns to consider rather than the ones
|
|
159
|
+
to ignore.
|
|
174
160
|
|
|
175
|
-
|
|
161
|
+
Can be useful when working with a legacy or shared database schema, or to make safe schema change
|
|
162
|
+
in two deploys rather than three.
|
|
176
163
|
|
|
177
|
-
*
|
|
164
|
+
*Anton Kandratski*
|
|
178
165
|
|
|
179
|
-
|
|
166
|
+
* Use `PG::Connection#close_prepared` (protocol level Close) to deallocate
|
|
167
|
+
prepared statements when available.
|
|
180
168
|
|
|
181
|
-
|
|
169
|
+
To enable its use, you must have pg >= 1.6.0, libpq >= 17, and a PostgreSQL
|
|
170
|
+
database version >= 17.
|
|
182
171
|
|
|
183
|
-
|
|
172
|
+
*Hartley McGuire*, *Andrew Jackson*
|
|
184
173
|
|
|
185
|
-
|
|
174
|
+
* Fix query cache for pinned connections in multi threaded transactional tests
|
|
186
175
|
|
|
187
|
-
|
|
188
|
-
|
|
176
|
+
When a pinned connection is used across separate threads, they now use a separate cache store
|
|
177
|
+
for each thread.
|
|
189
178
|
|
|
190
|
-
|
|
179
|
+
This improve accuracy of system tests, and any test using multiple threads.
|
|
191
180
|
|
|
192
|
-
*
|
|
181
|
+
*Heinrich Lee Yu*, *Jean Boussier*
|
|
193
182
|
|
|
194
|
-
|
|
183
|
+
* Fix time attribute dirty tracking with timezone conversions.
|
|
195
184
|
|
|
185
|
+
Time-only attributes now maintain a fixed date of 2000-01-01 during timezone conversions,
|
|
186
|
+
preventing them from being incorrectly marked as changed due to date shifts.
|
|
196
187
|
|
|
197
|
-
|
|
188
|
+
This fixes an issue where time attributes would be marked as changed when setting the same time value
|
|
189
|
+
due to timezone conversion causing internal date shifts.
|
|
198
190
|
|
|
199
|
-
*
|
|
191
|
+
*Prateek Choudhary*
|
|
200
192
|
|
|
201
|
-
|
|
193
|
+
* Skip calling `PG::Connection#cancel` in `cancel_any_running_query`
|
|
194
|
+
when using libpq >= 18 with pg < 1.6.0, due to incompatibility.
|
|
195
|
+
Rollback still runs, but may take longer.
|
|
202
196
|
|
|
203
|
-
*
|
|
204
|
-
singular association and having `index_nested_attribute_errors` enabled.
|
|
197
|
+
*Yasuo Honda*, *Lars Kanis*
|
|
205
198
|
|
|
206
|
-
|
|
199
|
+
* Don't add `id_value` attribute alias when attribute/column with that name already exists.
|
|
207
200
|
|
|
208
|
-
*
|
|
209
|
-
we want to reserve that name for a stronger sense of "immutable relation".
|
|
210
|
-
Please use `ActiveRecord::UnmodifiableRelation` instead.
|
|
201
|
+
*Rob Lewis*
|
|
211
202
|
|
|
212
|
-
|
|
203
|
+
* Remove deprecated `:unsigned_float` and `:unsigned_decimal` column methods for MySQL.
|
|
213
204
|
|
|
214
|
-
*
|
|
215
|
-
`DatabaseConfig`.
|
|
205
|
+
*Rafael Mendonça França*
|
|
216
206
|
|
|
217
|
-
|
|
207
|
+
* Remove deprecated `:retries` option for the SQLite3 adapter.
|
|
218
208
|
|
|
219
|
-
*
|
|
209
|
+
*Rafael Mendonça França*
|
|
220
210
|
|
|
221
|
-
|
|
211
|
+
* Introduce new database configuration options `keepalive`, `max_age`, and
|
|
212
|
+
`min_connections` -- and rename `pool` to `max_connections` to match.
|
|
222
213
|
|
|
223
|
-
|
|
214
|
+
There are no changes to default behavior, but these allow for more specific
|
|
215
|
+
control over pool behavior.
|
|
224
216
|
|
|
225
|
-
|
|
226
|
-
complements `transaction.active_record`, which is emitted when they finish.
|
|
217
|
+
*Matthew Draper*, *Chris AtLee*, *Rachael Wright-Munn*
|
|
227
218
|
|
|
228
|
-
|
|
219
|
+
* Move `LIMIT` validation from query generation to when `limit()` is called.
|
|
229
220
|
|
|
230
|
-
*
|
|
221
|
+
*Hartley McGuire*, *Shuyang*
|
|
231
222
|
|
|
232
|
-
*
|
|
233
|
-
for preloaded associations in models using composite primary keys.
|
|
223
|
+
* Add `ActiveRecord::CheckViolation` error class for check constraint violations.
|
|
234
224
|
|
|
235
|
-
*
|
|
225
|
+
*Ryuta Kamizono*
|
|
236
226
|
|
|
237
|
-
*
|
|
227
|
+
* Add `ActiveRecord::ExclusionViolation` error class for exclusion constraint violations.
|
|
238
228
|
|
|
239
|
-
|
|
229
|
+
When an exclusion constraint is violated in PostgreSQL, the error will now be raised
|
|
230
|
+
as `ActiveRecord::ExclusionViolation` instead of the generic `ActiveRecord::StatementInvalid`,
|
|
231
|
+
making it easier to handle these specific constraint violations in application code.
|
|
240
232
|
|
|
241
|
-
|
|
233
|
+
This follows the same pattern as other constraint violation error classes like
|
|
234
|
+
`RecordNotUnique` for unique constraint violations and `InvalidForeignKey` for
|
|
235
|
+
foreign key constraint violations.
|
|
242
236
|
|
|
243
|
-
*
|
|
237
|
+
*Ryuta Kamizono*
|
|
244
238
|
|
|
245
|
-
*
|
|
239
|
+
* Attributes filtered by `filter_attributes` will now also be filtered by `filter_parameters`
|
|
240
|
+
so sensitive information is not leaked.
|
|
246
241
|
|
|
247
|
-
*
|
|
242
|
+
*Jill Klang*
|
|
248
243
|
|
|
249
|
-
*
|
|
244
|
+
* Add `connection.current_transaction.isolation` API to check current transaction's isolation level.
|
|
250
245
|
|
|
251
|
-
|
|
246
|
+
Returns the isolation level if it was explicitly set via the `isolation:` parameter
|
|
247
|
+
or through `ActiveRecord.with_transaction_isolation_level`, otherwise returns `nil`.
|
|
248
|
+
Nested transactions return the parent transaction's isolation level.
|
|
252
249
|
|
|
253
250
|
```ruby
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
end
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
Before, `#post` would infer the model as `Nested::Post`, but now it correctly infers `Post`.
|
|
260
|
-
|
|
261
|
-
*Joshua Young*
|
|
262
|
-
|
|
263
|
-
* PostgreSQL `Cidr#change?` detects the address prefix change.
|
|
251
|
+
# Returns nil when no transaction
|
|
252
|
+
User.connection.current_transaction.isolation # => nil
|
|
264
253
|
|
|
265
|
-
|
|
254
|
+
# Returns explicitly set isolation level
|
|
255
|
+
User.transaction(isolation: :serializable) do
|
|
256
|
+
User.connection.current_transaction.isolation # => :serializable
|
|
257
|
+
end
|
|
266
258
|
|
|
267
|
-
|
|
259
|
+
# Returns nil when isolation not explicitly set
|
|
260
|
+
User.transaction do
|
|
261
|
+
User.connection.current_transaction.isolation # => nil
|
|
262
|
+
end
|
|
268
263
|
|
|
269
|
-
|
|
264
|
+
# Nested transactions inherit parent's isolation
|
|
265
|
+
User.transaction(isolation: :read_committed) do
|
|
266
|
+
User.transaction do
|
|
267
|
+
User.connection.current_transaction.isolation # => :read_committed
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
```
|
|
270
271
|
|
|
271
|
-
*
|
|
272
|
+
*Kir Shatrov*
|
|
272
273
|
|
|
273
|
-
*
|
|
274
|
+
* Fix `#merge` with `#or` or `#and` and a mixture of attributes and SQL strings resulting in an incorrect query.
|
|
274
275
|
|
|
275
276
|
```ruby
|
|
276
|
-
|
|
277
|
+
base = Comment.joins(:post).where(user_id: 1).where("recent = 1")
|
|
278
|
+
puts base.merge(base.where(draft: true).or(Post.where(archived: true))).to_sql
|
|
277
279
|
```
|
|
278
280
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
* Add support for `:if_not_exists` and `:force` options to `create_schema`.
|
|
282
|
-
|
|
283
|
-
*fatkodima*
|
|
284
|
-
|
|
285
|
-
* Fix `index_errors` having incorrect index in association validation errors.
|
|
286
|
-
|
|
287
|
-
*lulalala*
|
|
288
|
-
|
|
289
|
-
* Add `index_errors: :nested_attributes_order` mode.
|
|
290
|
-
|
|
291
|
-
This indexes the association validation errors based on the order received by nested attributes setter, and respects the `reject_if` configuration. This enables API to provide enough information to the frontend to map the validation errors back to their respective form fields.
|
|
292
|
-
|
|
293
|
-
*lulalala*
|
|
294
|
-
|
|
295
|
-
* Add `Rails.application.config.active_record.postgresql_adapter_decode_dates` to opt out of decoding dates automatically with the postgresql adapter. Defaults to true.
|
|
296
|
-
|
|
297
|
-
*Joé Dupuis*
|
|
298
|
-
|
|
299
|
-
* Association option `query_constraints` is deprecated in favor of `foreign_key`.
|
|
300
|
-
|
|
301
|
-
*Nikita Vasilevsky*
|
|
302
|
-
|
|
303
|
-
* Add `ENV["SKIP_TEST_DATABASE_TRUNCATE"]` flag to speed up multi-process test runs on large DBs when all tests run within default transaction.
|
|
304
|
-
|
|
305
|
-
This cuts ~10s from the test run of HEY when run by 24 processes against the 178 tables, since ~4,000 table truncates can then be skipped.
|
|
306
|
-
|
|
307
|
-
*DHH*
|
|
308
|
-
|
|
309
|
-
* Added support for recursive common table expressions.
|
|
281
|
+
Before:
|
|
310
282
|
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
283
|
+
```SQL
|
|
284
|
+
SELECT "comments".* FROM "comments"
|
|
285
|
+
INNER JOIN "posts" ON "posts"."id" = "comments"."post_id"
|
|
286
|
+
WHERE (recent = 1)
|
|
287
|
+
AND (
|
|
288
|
+
"comments"."user_id" = 1
|
|
289
|
+
AND (recent = 1)
|
|
290
|
+
AND "comments"."draft" = 1
|
|
291
|
+
OR "posts"."archived" = 1
|
|
317
292
|
)
|
|
318
293
|
```
|
|
319
294
|
|
|
320
|
-
|
|
295
|
+
After:
|
|
321
296
|
|
|
322
|
-
```
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
297
|
+
```SQL
|
|
298
|
+
SELECT "comments".* FROM "comments"
|
|
299
|
+
INNER JOIN "posts" ON "posts"."id" = "comments"."post_id"
|
|
300
|
+
WHERE "comments"."user_id" = 1
|
|
301
|
+
AND (recent = 1)
|
|
302
|
+
AND (
|
|
303
|
+
"comments"."user_id" = 1
|
|
304
|
+
AND (recent = 1)
|
|
305
|
+
AND "comments"."draft" = 1
|
|
306
|
+
OR "posts"."archived" = 1
|
|
327
307
|
)
|
|
328
|
-
SELECT "posts".* FROM "posts"
|
|
329
308
|
```
|
|
330
309
|
|
|
331
|
-
*
|
|
332
|
-
|
|
333
|
-
* `validate_constraint` can be called in a `change_table` block.
|
|
310
|
+
*Joshua Young*
|
|
334
311
|
|
|
335
|
-
|
|
336
|
-
```ruby
|
|
337
|
-
change_table :products do |t|
|
|
338
|
-
t.check_constraint "price > discounted_price", name: "price_check", validate: false
|
|
339
|
-
t.validate_check_constraint "price_check"
|
|
340
|
-
end
|
|
341
|
-
```
|
|
312
|
+
* Make schema dumper to account for `ActiveRecord.dump_schemas` when dumping in `:ruby` format.
|
|
342
313
|
|
|
343
|
-
*
|
|
314
|
+
*fatkodima*
|
|
344
315
|
|
|
345
|
-
* `
|
|
316
|
+
* Add `:touch` option to `update_column`/`update_columns` methods.
|
|
346
317
|
|
|
347
|
-
Ex:
|
|
348
318
|
```ruby
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
```
|
|
352
|
-
|
|
353
|
-
*Joé Dupuis*
|
|
319
|
+
# Will update :updated_at/:updated_on alongside :nice column.
|
|
320
|
+
user.update_column(:nice, true, touch: true)
|
|
354
321
|
|
|
355
|
-
|
|
322
|
+
# Will update :updated_at/:updated_on alongside :last_ip column
|
|
323
|
+
user.update_columns(last_ip: request.remote_ip, touch: true)
|
|
324
|
+
```
|
|
356
325
|
|
|
357
|
-
|
|
358
|
-
match intended behavior and to prevent non-deterministic order issues caused
|
|
359
|
-
by calling methods like `first` or `last`. As `first` and `last` don't cause
|
|
360
|
-
an N+1 by themselves, calling child associations will no longer raise.
|
|
361
|
-
Fixes #49473.
|
|
326
|
+
*Dmitrii Ivliev*
|
|
362
327
|
|
|
363
|
-
|
|
328
|
+
* Optimize Active Record batching further when using ranges.
|
|
364
329
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
person.posts.first
|
|
369
|
-
# SELECT * FROM posts WHERE person_id = 1; -- non-deterministic order
|
|
370
|
-
person.posts.first.firm # raises ActiveRecord::StrictLoadingViolationError
|
|
371
|
-
```
|
|
330
|
+
Tested on a PostgreSQL table with 10M records and batches of 10k records, the generation
|
|
331
|
+
of relations for the 1000 batches was `4.8x` faster (`6.8s` vs. `1.4s`), used `900x`
|
|
332
|
+
less bandwidth (`180MB` vs. `0.2MB`) and allocated `45x` less memory (`490MB` vs. `11MB`).
|
|
372
333
|
|
|
373
|
-
|
|
334
|
+
*Maxime Réty*, *fatkodima*
|
|
374
335
|
|
|
375
|
-
|
|
376
|
-
person = Person.find(1)
|
|
377
|
-
person.strict_loading!(mode: :n_plus_one_only)
|
|
378
|
-
person.posts.first # this is 1+1, not N+1
|
|
379
|
-
# SELECT * FROM posts WHERE person_id = 1 ORDER BY id LIMIT 1;
|
|
380
|
-
person.posts.first.firm # no longer raises
|
|
381
|
-
```
|
|
336
|
+
* Include current character length in error messages for index and table name length validations.
|
|
382
337
|
|
|
383
|
-
*
|
|
338
|
+
*Joshua Young*
|
|
384
339
|
|
|
385
|
-
*
|
|
340
|
+
* Add `rename_schema` method for PostgreSQL.
|
|
386
341
|
|
|
387
|
-
*
|
|
342
|
+
*T S Vallender*
|
|
388
343
|
|
|
389
|
-
*
|
|
344
|
+
* Implement support for deprecating associations:
|
|
390
345
|
|
|
391
346
|
```ruby
|
|
392
|
-
|
|
393
|
-
Post.joins(:comments).pluck("posts.id", "comments.id", "comments.body")
|
|
394
|
-
|
|
395
|
-
# After
|
|
396
|
-
Post.joins(:comments).pluck(posts: [:id], comments: [:id, :body])
|
|
347
|
+
has_many :posts, deprecated: true
|
|
397
348
|
```
|
|
398
349
|
|
|
399
|
-
|
|
350
|
+
With that, Active Record will report any usage of the `posts` association.
|
|
400
351
|
|
|
401
|
-
|
|
352
|
+
Three reporting modes are supported (`:warn`, `:raise`, and `:notify`), and
|
|
353
|
+
backtraces can be enabled or disabled. Defaults are `:warn` mode and
|
|
354
|
+
disabled backtraces.
|
|
402
355
|
|
|
403
|
-
|
|
356
|
+
Please, check the docs for further details.
|
|
404
357
|
|
|
405
|
-
*
|
|
358
|
+
*Xavier Noria*
|
|
406
359
|
|
|
407
|
-
|
|
360
|
+
* PostgreSQL adapter create DB now supports `locale_provider` and `locale`.
|
|
408
361
|
|
|
409
|
-
|
|
410
|
-
Article.transaction do |transaction|
|
|
411
|
-
article.update(published: true)
|
|
412
|
-
transaction.after_commit do
|
|
413
|
-
PublishNotificationMailer.with(article: article).deliver_later
|
|
414
|
-
end
|
|
415
|
-
end
|
|
416
|
-
```
|
|
362
|
+
*Bengt-Ove Hollaender*
|
|
417
363
|
|
|
418
|
-
|
|
364
|
+
* Use ntuples to populate row_count instead of count for Postgres
|
|
419
365
|
|
|
420
|
-
*
|
|
366
|
+
*Jonathan Calvert*
|
|
421
367
|
|
|
422
|
-
|
|
368
|
+
* Fix checking whether an unpersisted record is `include?`d in a strictly
|
|
369
|
+
loaded `has_and_belongs_to_many` association.
|
|
423
370
|
|
|
424
|
-
|
|
425
|
-
Article.current_transaction.after_commit do
|
|
426
|
-
PublishNotificationMailer.with(article: article).deliver_later
|
|
427
|
-
end
|
|
428
|
-
```
|
|
371
|
+
*Hartley McGuire*
|
|
429
372
|
|
|
430
|
-
|
|
373
|
+
* Add ability to change transaction isolation for all pools within a block.
|
|
431
374
|
|
|
432
|
-
|
|
375
|
+
This functionality is useful if your application needs to change the database
|
|
376
|
+
transaction isolation for a request or action.
|
|
433
377
|
|
|
434
|
-
|
|
435
|
-
|
|
378
|
+
Calling `ActiveRecord.with_transaction_isolation_level(level) {}` in an around filter or
|
|
379
|
+
middleware will set the transaction isolation for all pools accessed within the block,
|
|
380
|
+
but not for the pools that aren't.
|
|
381
|
+
|
|
382
|
+
This works with explicit and implicit transactions:
|
|
436
383
|
|
|
437
384
|
```ruby
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
PublishNotificationMailer.with(article: article).deliver_later
|
|
385
|
+
ActiveRecord.with_transaction_isolation_level(:read_committed) do
|
|
386
|
+
Tag.transaction do # opens a transaction explicitly
|
|
387
|
+
Tag.create!
|
|
442
388
|
end
|
|
443
389
|
end
|
|
444
390
|
```
|
|
445
391
|
|
|
446
|
-
In the above example, the block is either executed immediately if called outside
|
|
447
|
-
of a transaction, or called after the open transaction is committed.
|
|
448
|
-
|
|
449
|
-
If the transaction is rolled back, the block isn't called.
|
|
450
|
-
|
|
451
|
-
*Jean Boussier*
|
|
452
|
-
|
|
453
|
-
* Add the ability to ignore counter cache columns until they are backfilled.
|
|
454
|
-
|
|
455
|
-
Starting to use counter caches on existing large tables can be troublesome, because the column
|
|
456
|
-
values must be backfilled separately of the column addition (to not lock the table for too long)
|
|
457
|
-
and before the use of `:counter_cache` (otherwise methods like `size`/`any?`/etc, which use
|
|
458
|
-
counter caches internally, can produce incorrect results). People usually use database triggers
|
|
459
|
-
or callbacks on child associations while backfilling before introducing a counter cache
|
|
460
|
-
configuration to the association.
|
|
461
|
-
|
|
462
|
-
Now, to safely backfill the column, while keeping the column updated with child records added/removed, use:
|
|
463
|
-
|
|
464
392
|
```ruby
|
|
465
|
-
|
|
466
|
-
|
|
393
|
+
ActiveRecord.with_transaction_isolation_level(:read_committed) do
|
|
394
|
+
Tag.create! # opens a transaction implicitly
|
|
467
395
|
end
|
|
468
396
|
```
|
|
469
397
|
|
|
470
|
-
|
|
471
|
-
but get the results directly from the database. After the counter cache column is backfilled, simply
|
|
472
|
-
remove the `{ active: false }` part from the counter cache definition, and it will now be used by the
|
|
473
|
-
mentioned methods.
|
|
474
|
-
|
|
475
|
-
*fatkodima*
|
|
398
|
+
*Eileen M. Uchitelle*
|
|
476
399
|
|
|
477
|
-
*
|
|
400
|
+
* Raise `ActiveRecord::MissingRequiredOrderError` when order dependent finder methods (e.g. `#first`, `#last`) are
|
|
401
|
+
called without `order` values on the relation, and the model does not have any order columns (`implicit_order_column`,
|
|
402
|
+
`query_constraints`, or `primary_key`) to fall back on.
|
|
478
403
|
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
adapters such as `TrilogyAdapter` would raise `ActiveRecord::ConnectionFailed: Trilogy::EOFError`
|
|
482
|
-
when encountering a connection error mid-request.
|
|
404
|
+
This change will be introduced with a new framework default for Rails 8.1, and the current behavior of not raising
|
|
405
|
+
an error has been deprecated with the aim of removing the configuration option in Rails 8.2.
|
|
483
406
|
|
|
484
|
-
|
|
407
|
+
```ruby
|
|
408
|
+
config.active_record.raise_on_missing_required_finder_order_columns = true
|
|
409
|
+
```
|
|
485
410
|
|
|
486
|
-
*
|
|
411
|
+
*Joshua Young*
|
|
487
412
|
|
|
488
|
-
|
|
489
|
-
Now it's possible to pass an Array value as `foreign_key` to achieve the same behavior of an association.
|
|
413
|
+
* `:class_name` is now invalid in polymorphic `belongs_to` associations.
|
|
490
414
|
|
|
491
|
-
|
|
415
|
+
Reason is `:class_name` does not make sense in those associations because
|
|
416
|
+
the class name of target records is dynamic and stored in the type column.
|
|
492
417
|
|
|
493
|
-
|
|
418
|
+
Existing polymorphic associations setting this option can just delete it.
|
|
419
|
+
While it did not raise, it had no effect anyway.
|
|
494
420
|
|
|
495
|
-
|
|
496
|
-
Now it's possible to explicitly set it as composite on the association.
|
|
421
|
+
*Xavier Noria*
|
|
497
422
|
|
|
498
|
-
|
|
423
|
+
* Add support for multiple databases to `db:migrate:reset`.
|
|
499
424
|
|
|
500
|
-
*
|
|
425
|
+
*Joé Dupuis*
|
|
501
426
|
|
|
502
|
-
|
|
427
|
+
* Add `affected_rows` to `ActiveRecord::Result`.
|
|
503
428
|
|
|
504
|
-
|
|
505
|
-
the request or job. This behavior can be undesirable in environments that use many more threads or fibers than there
|
|
506
|
-
is available connections.
|
|
429
|
+
*Jenny Shen*
|
|
507
430
|
|
|
508
|
-
|
|
509
|
-
migrate it to use `ActiveRecord::Base.with_connection` instead.
|
|
431
|
+
* Enable passing retryable SqlLiterals to `#where`.
|
|
510
432
|
|
|
511
|
-
|
|
433
|
+
*Hartley McGuire*
|
|
512
434
|
|
|
513
|
-
|
|
435
|
+
* Set default for primary keys in `insert_all`/`upsert_all`.
|
|
514
436
|
|
|
515
|
-
|
|
437
|
+
Previously in Postgres, updating and inserting new records in one upsert wasn't possible
|
|
438
|
+
due to null primary key values. `nil` primary key values passed into `insert_all`/`upsert_all`
|
|
439
|
+
are now implicitly set to the default insert value specified by adapter.
|
|
516
440
|
|
|
517
|
-
|
|
518
|
-
`ActiveRecord::ConnectionAdapters::ConnectionPool#uncached`.
|
|
441
|
+
*Jenny Shen*
|
|
519
442
|
|
|
520
|
-
|
|
521
|
-
When set to `false`, writes to the affected connection pool will not clear any query cache.
|
|
443
|
+
* Add a load hook `active_record_database_configurations` for `ActiveRecord::DatabaseConfigurations`
|
|
522
444
|
|
|
523
|
-
|
|
445
|
+
*Mike Dalessio*
|
|
524
446
|
|
|
525
|
-
|
|
447
|
+
* Use `TRUE` and `FALSE` for SQLite queries with boolean columns.
|
|
526
448
|
|
|
527
|
-
*
|
|
449
|
+
*Hartley McGuire*
|
|
528
450
|
|
|
529
|
-
|
|
530
|
-
connection will be held for the duration of the request or job.
|
|
451
|
+
* Bump minimum supported SQLite to 3.23.0.
|
|
531
452
|
|
|
532
|
-
|
|
533
|
-
current plan to remove the method.
|
|
453
|
+
*Hartley McGuire*
|
|
534
454
|
|
|
535
|
-
|
|
455
|
+
* Allow allocated Active Records to lookup associations.
|
|
536
456
|
|
|
537
|
-
|
|
457
|
+
Previously, the association cache isn't setup on allocated record objects, so association
|
|
458
|
+
lookups will crash. Test frameworks like mocha use allocate to check for stubbable instance
|
|
459
|
+
methods, which can trigger an association lookup.
|
|
538
460
|
|
|
539
|
-
|
|
540
|
-
connection will be held for the duration of the request or job.
|
|
461
|
+
*Gannon McGibbon*
|
|
541
462
|
|
|
542
|
-
|
|
463
|
+
* Encryption now supports `support_unencrypted_data: true` being set per-attribute.
|
|
543
464
|
|
|
544
|
-
|
|
465
|
+
Previously this only worked if `ActiveRecord::Encryption.config.support_unencrypted_data == true`.
|
|
466
|
+
Now, if the global config is turned off, you can still opt in for a specific attribute.
|
|
545
467
|
|
|
546
468
|
```ruby
|
|
547
|
-
|
|
548
|
-
|
|
469
|
+
# ActiveRecord::Encryption.config.support_unencrypted_data = true
|
|
470
|
+
class User < ActiveRecord::Base
|
|
471
|
+
encrypts :name, support_unencrypted_data: false # only supports encrypted data
|
|
472
|
+
encrypts :email # supports encrypted or unencrypted data
|
|
473
|
+
end
|
|
549
474
|
```
|
|
550
475
|
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
*Joshua Young*
|
|
559
|
-
|
|
560
|
-
* Fix `has_one` association autosave setting the foreign key attribute when it is unchanged.
|
|
561
|
-
|
|
562
|
-
This behavior is also inconsistent with autosaving `belongs_to` and can have unintended side effects like raising
|
|
563
|
-
an `ActiveRecord::ReadonlyAttributeError` when the foreign key attribute is marked as read-only.
|
|
564
|
-
|
|
565
|
-
*Joshua Young*
|
|
566
|
-
|
|
567
|
-
* Remove deprecated behavior that would rollback a transaction block when exited using `return`, `break` or `throw`.
|
|
568
|
-
|
|
569
|
-
*Rafael Mendonça França*
|
|
570
|
-
|
|
571
|
-
* Deprecate `Rails.application.config.active_record.commit_transaction_on_non_local_return`.
|
|
572
|
-
|
|
573
|
-
*Rafael Mendonça França*
|
|
574
|
-
|
|
575
|
-
* Remove deprecated support to pass `rewhere` to `ActiveRecord::Relation#merge`.
|
|
576
|
-
|
|
577
|
-
*Rafael Mendonça França*
|
|
578
|
-
|
|
579
|
-
* Remove deprecated support to pass `deferrable: true` to `add_foreign_key`.
|
|
580
|
-
|
|
581
|
-
*Rafael Mendonça França*
|
|
582
|
-
|
|
583
|
-
* Remove deprecated support to quote `ActiveSupport::Duration`.
|
|
584
|
-
|
|
585
|
-
*Rafael Mendonça França*
|
|
586
|
-
|
|
587
|
-
* Remove deprecated `#quote_bound_value`.
|
|
588
|
-
|
|
589
|
-
*Rafael Mendonça França*
|
|
590
|
-
|
|
591
|
-
* Remove deprecated `ActiveRecord::ConnectionAdapters::ConnectionPool#connection_klass`.
|
|
592
|
-
|
|
593
|
-
*Rafael Mendonça França*
|
|
594
|
-
|
|
595
|
-
* Remove deprecated support to apply `#connection_pool_list`, `#active_connections?`, `#clear_active_connections!`,
|
|
596
|
-
`#clear_reloadable_connections!`, `#clear_all_connections!` and `#flush_idle_connections!` to the connections pools
|
|
597
|
-
for the current role when the `role` argument isn't provided.
|
|
598
|
-
|
|
599
|
-
*Rafael Mendonça França*
|
|
600
|
-
|
|
601
|
-
* Remove deprecated `#all_connection_pools`.
|
|
476
|
+
```ruby
|
|
477
|
+
# ActiveRecord::Encryption.config.support_unencrypted_data = false
|
|
478
|
+
class User < ActiveRecord::Base
|
|
479
|
+
encrypts :name, support_unencrypted_data: true # supports encrypted or unencrypted data
|
|
480
|
+
encrypts :email # only supports encrypted data
|
|
481
|
+
end
|
|
482
|
+
```
|
|
602
483
|
|
|
603
|
-
*
|
|
484
|
+
*Alex Ghiculescu*
|
|
604
485
|
|
|
605
|
-
*
|
|
486
|
+
* Model generator no longer needs a database connection to validate column types.
|
|
606
487
|
|
|
607
|
-
*
|
|
488
|
+
*Mike Dalessio*
|
|
608
489
|
|
|
609
|
-
*
|
|
490
|
+
* Allow signed ID verifiers to be configurable via `Rails.application.message_verifiers`
|
|
610
491
|
|
|
611
|
-
|
|
492
|
+
Prior to this change, the primary way to configure signed ID verifiers was
|
|
493
|
+
to set `signed_id_verifier` on each model class:
|
|
612
494
|
|
|
613
|
-
|
|
495
|
+
```ruby
|
|
496
|
+
Post.signed_id_verifier = ActiveSupport::MessageVerifier.new(...)
|
|
497
|
+
Comment.signed_id_verifier = ActiveSupport::MessageVerifier.new(...)
|
|
498
|
+
```
|
|
614
499
|
|
|
615
|
-
|
|
500
|
+
And if the developer did not set `signed_id_verifier`, a verifier would be
|
|
501
|
+
instantiated with a secret derived from `secret_key_base` and the following
|
|
502
|
+
options:
|
|
616
503
|
|
|
617
|
-
|
|
504
|
+
```ruby
|
|
505
|
+
{ digest: "SHA256", serializer: JSON, url_safe: true }
|
|
506
|
+
```
|
|
618
507
|
|
|
619
|
-
|
|
508
|
+
Thus it was cumbersome to rotate configuration for all verifiers.
|
|
620
509
|
|
|
621
|
-
|
|
510
|
+
This change defines a new Rails config: [`config.active_record.use_legacy_signed_id_verifier`][].
|
|
511
|
+
The default value is `:generate_and_verify`, which preserves the previous
|
|
512
|
+
behavior. However, when set to `:verify`, signed ID verifiers will use
|
|
513
|
+
configuration from `Rails.application.message_verifiers` (specifically,
|
|
514
|
+
`Rails.application.message_verifiers["active_record/signed_id"]`) to
|
|
515
|
+
generate and verify signed IDs, but will also verify signed IDs using the
|
|
516
|
+
older configuration.
|
|
622
517
|
|
|
623
|
-
|
|
518
|
+
To avoid complication, the new behavior only applies when `signed_id_verifier_secret`
|
|
519
|
+
is not set on a model class or any of its ancestors. Additionally,
|
|
520
|
+
`signed_id_verifier_secret` is now deprecated. If you are currently setting
|
|
521
|
+
`signed_id_verifier_secret` on a model class, you can set `signed_id_verifier`
|
|
522
|
+
instead:
|
|
624
523
|
|
|
625
|
-
|
|
524
|
+
```ruby
|
|
525
|
+
# BEFORE
|
|
526
|
+
Post.signed_id_verifier_secret = "my secret"
|
|
626
527
|
|
|
627
|
-
|
|
528
|
+
# AFTER
|
|
529
|
+
Post.signed_id_verifier = ActiveSupport::MessageVerifier.new("my secret", digest: "SHA256", serializer: JSON, url_safe: true)
|
|
530
|
+
```
|
|
628
531
|
|
|
629
|
-
|
|
532
|
+
To ease migration, `signed_id_verifier` has also been changed to behave as a
|
|
533
|
+
`class_attribute` (i.e. inheritable), but _only when `signed_id_verifier_secret`
|
|
534
|
+
is not set_:
|
|
630
535
|
|
|
631
|
-
|
|
536
|
+
```ruby
|
|
537
|
+
# BEFORE
|
|
538
|
+
ActiveRecord::Base.signed_id_verifier = ActiveSupport::MessageVerifier.new(...)
|
|
539
|
+
Post.signed_id_verifier == ActiveRecord::Base.signed_id_verifier # => false
|
|
632
540
|
|
|
633
|
-
|
|
541
|
+
# AFTER
|
|
542
|
+
ActiveRecord::Base.signed_id_verifier = ActiveSupport::MessageVerifier.new(...)
|
|
543
|
+
Post.signed_id_verifier == ActiveRecord::Base.signed_id_verifier # => true
|
|
634
544
|
|
|
635
|
-
|
|
545
|
+
Post.signed_id_verifier_secret = "my secret" # => deprecation warning
|
|
546
|
+
Post.signed_id_verifier == ActiveRecord::Base.signed_id_verifier # => false
|
|
547
|
+
```
|
|
636
548
|
|
|
637
|
-
|
|
638
|
-
|
|
549
|
+
Note, however, that it is recommended to eventually migrate from
|
|
550
|
+
model-specific verifiers to a unified configuration managed by
|
|
551
|
+
`Rails.application.message_verifiers`. `ActiveSupport::MessageVerifier#rotate`
|
|
552
|
+
can facilitate that transition. For example:
|
|
639
553
|
|
|
640
|
-
|
|
554
|
+
```ruby
|
|
555
|
+
# BEFORE
|
|
556
|
+
# Generate and verify signed Post IDs using Post-specific configuration
|
|
557
|
+
Post.signed_id_verifier = ActiveSupport::MessageVerifier.new("post secret", ...)
|
|
641
558
|
|
|
642
|
-
|
|
559
|
+
# AFTER
|
|
560
|
+
# Generate and verify signed Post IDs using the unified configuration
|
|
561
|
+
Post.signed_id_verifier = Post.signed_id_verifier.dup
|
|
562
|
+
# Fall back to Post-specific configuration when verifying signed IDs
|
|
563
|
+
Post.signed_id_verifier.rotate("post secret", ...)
|
|
564
|
+
```
|
|
643
565
|
|
|
644
|
-
|
|
566
|
+
[`config.active_record.use_legacy_signed_id_verifier`]: https://guides.rubyonrails.org/v8.1/configuring.html#config-active-record-use-legacy-signed-id-verifier
|
|
645
567
|
|
|
646
|
-
*
|
|
568
|
+
*Ali Sepehri*, *Jonathan Hefner*
|
|
647
569
|
|
|
648
|
-
|
|
570
|
+
* Prepend `extra_flags` in postgres' `structure_load`
|
|
649
571
|
|
|
650
|
-
|
|
572
|
+
When specifying `structure_load_flags` with a postgres adapter, the flags
|
|
573
|
+
were appended to the default flags, instead of prepended.
|
|
574
|
+
This caused issues with flags not being taken into account by postgres.
|
|
651
575
|
|
|
652
|
-
*
|
|
576
|
+
*Alice Loeser*
|
|
653
577
|
|
|
654
|
-
*
|
|
578
|
+
* Allow bypassing primary key/constraint addition in `implicit_order_column`
|
|
655
579
|
|
|
656
|
-
|
|
580
|
+
When specifying multiple columns in an array for `implicit_order_column`, adding
|
|
581
|
+
`nil` as the last element will prevent appending the primary key to order
|
|
582
|
+
conditions. This allows more precise control of indexes used by
|
|
583
|
+
generated queries. It should be noted that this feature does introduce the risk
|
|
584
|
+
of API misbehavior if the specified columns are not fully unique.
|
|
657
585
|
|
|
658
|
-
*
|
|
586
|
+
*Issy Long*
|
|
659
587
|
|
|
660
|
-
|
|
588
|
+
* Allow setting the `schema_format` via database configuration.
|
|
661
589
|
|
|
662
|
-
|
|
590
|
+
```
|
|
591
|
+
primary:
|
|
592
|
+
schema_format: ruby
|
|
593
|
+
```
|
|
663
594
|
|
|
664
|
-
|
|
595
|
+
Useful for multi-database setups when apps require different formats per-database.
|
|
665
596
|
|
|
666
|
-
*
|
|
597
|
+
*T S Vallender*
|
|
667
598
|
|
|
668
|
-
|
|
599
|
+
* Support disabling indexes for MySQL v8.0.0+ and MariaDB v10.6.0+
|
|
669
600
|
|
|
670
|
-
|
|
601
|
+
MySQL 8.0.0 added an option to disable indexes from being used by the query
|
|
602
|
+
optimizer by making them "invisible". This allows the index to still be maintained
|
|
603
|
+
and updated but no queries will be permitted to use it. This can be useful for adding
|
|
604
|
+
new invisible indexes or making existing indexes invisible before dropping them
|
|
605
|
+
to ensure queries are not negatively affected.
|
|
606
|
+
See https://dev.mysql.com/blog-archive/mysql-8-0-invisible-indexes/ for more details.
|
|
671
607
|
|
|
672
|
-
|
|
608
|
+
MariaDB 10.6.0 also added support for this feature by allowing indexes to be "ignored"
|
|
609
|
+
in queries. See https://mariadb.com/kb/en/ignored-indexes/ for more details.
|
|
673
610
|
|
|
674
|
-
|
|
611
|
+
Active Record now supports this option for MySQL 8.0.0+ and MariaDB 10.6.0+ for
|
|
612
|
+
index creation and alteration where the new index option `enabled: true/false` can be
|
|
613
|
+
passed to column and index methods as below:
|
|
675
614
|
|
|
676
|
-
|
|
615
|
+
```ruby
|
|
616
|
+
add_index :users, :email, enabled: false
|
|
617
|
+
enable_index :users, :email
|
|
618
|
+
add_column :users, :dob, :string, index: { enabled: false }
|
|
619
|
+
|
|
620
|
+
change_table :users do |t|
|
|
621
|
+
t.index :name, enabled: false
|
|
622
|
+
t.index :dob
|
|
623
|
+
t.disable_index :dob
|
|
624
|
+
t.column :username, :string, index: { enabled: false }
|
|
625
|
+
t.references :account, index: { enabled: false }
|
|
626
|
+
end
|
|
677
627
|
|
|
678
|
-
|
|
628
|
+
create_table :users do |t|
|
|
629
|
+
t.string :name, index: { enabled: false }
|
|
630
|
+
t.string :email
|
|
631
|
+
t.index :email, enabled: false
|
|
632
|
+
end
|
|
633
|
+
```
|
|
679
634
|
|
|
680
|
-
*
|
|
635
|
+
*Merve Taner*
|
|
681
636
|
|
|
682
|
-
*
|
|
637
|
+
* Respect `implicit_order_column` in `ActiveRecord::Relation#reverse_order`.
|
|
683
638
|
|
|
684
|
-
*
|
|
639
|
+
*Joshua Young*
|
|
685
640
|
|
|
686
|
-
*
|
|
641
|
+
* Add column types to `ActiveRecord::Result` for SQLite3.
|
|
687
642
|
|
|
688
|
-
*
|
|
643
|
+
*Andrew Kane*
|
|
689
644
|
|
|
690
|
-
*
|
|
645
|
+
* Raise `ActiveRecord::ReadOnlyError` when pessimistically locking with a readonly role.
|
|
691
646
|
|
|
692
|
-
*
|
|
647
|
+
*Joshua Young*
|
|
693
648
|
|
|
694
|
-
*
|
|
649
|
+
* Fix using the `SQLite3Adapter`'s `dbconsole` method outside of a Rails application.
|
|
695
650
|
|
|
696
|
-
|
|
651
|
+
*Hartley McGuire*
|
|
697
652
|
|
|
698
|
-
|
|
699
|
-
used by the default serializer.
|
|
653
|
+
* Fix migrating multiple databases with `ActiveRecord::PendingMigration` action.
|
|
700
654
|
|
|
701
|
-
*
|
|
655
|
+
*Gannon McGibbon*
|
|
702
656
|
|
|
703
|
-
*
|
|
657
|
+
* Enable automatically retrying idempotent association queries on connection
|
|
658
|
+
errors.
|
|
704
659
|
|
|
705
|
-
|
|
660
|
+
*Hartley McGuire*
|
|
706
661
|
|
|
707
|
-
|
|
708
|
-
incidentally worked for MySQL and SQLite, but not PostgreSQL.
|
|
662
|
+
* Add `allow_retry` to `sql.active_record` instrumentation.
|
|
709
663
|
|
|
710
|
-
|
|
664
|
+
This enables identifying queries which queries are automatically retryable on connection errors.
|
|
711
665
|
|
|
712
|
-
*
|
|
666
|
+
*Hartley McGuire*
|
|
713
667
|
|
|
714
|
-
|
|
668
|
+
* Better support UPDATE with JOIN for Postgresql and SQLite3
|
|
715
669
|
|
|
716
|
-
|
|
670
|
+
Previously when generating update queries with one or more JOIN clauses,
|
|
671
|
+
Active Record would use a sub query which would prevent to reference the joined
|
|
672
|
+
tables in the `SET` clause, for instance:
|
|
717
673
|
|
|
718
|
-
|
|
719
|
-
|
|
674
|
+
```ruby
|
|
675
|
+
Comment.joins(:post).update_all("title = posts.title")
|
|
676
|
+
```
|
|
720
677
|
|
|
721
|
-
This is
|
|
722
|
-
|
|
678
|
+
This is now supported as long as the relation doesn't also use a `LIMIT`, `ORDER` or
|
|
679
|
+
`GROUP BY` clause. This was supported by the MySQL adapter for a long time.
|
|
723
680
|
|
|
724
681
|
*Jean Boussier*
|
|
725
682
|
|
|
726
|
-
*
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
*Jason Nochlin*
|
|
683
|
+
* Introduce a before-fork hook in `ActiveSupport::Testing::Parallelization` to clear existing
|
|
684
|
+
connections, to avoid fork-safety issues with the mysql2 adapter.
|
|
730
685
|
|
|
731
|
-
|
|
732
|
-
(either inner join or left outer join) based on the existing joins in the scope.
|
|
686
|
+
Fixes #41776
|
|
733
687
|
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
Example:
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
```ruby
|
|
741
|
-
# `associated` will use `LEFT JOIN` instead of using `JOIN`
|
|
742
|
-
Post.left_joins(:author).where.associated(:author)
|
|
743
|
-
```
|
|
688
|
+
*Mike Dalessio*, *Donal McBreen*
|
|
744
689
|
|
|
745
|
-
|
|
690
|
+
* PoolConfig no longer keeps a reference to the connection class.
|
|
746
691
|
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
could be misconfigured in some cases.
|
|
692
|
+
Keeping a reference to the class caused subtle issues when combined with reloading in
|
|
693
|
+
development. Fixes #54343.
|
|
750
694
|
|
|
751
|
-
*
|
|
695
|
+
*Mike Dalessio*
|
|
752
696
|
|
|
753
|
-
*
|
|
697
|
+
* Fix SQL notifications sometimes not sent when using async queries.
|
|
754
698
|
|
|
755
699
|
```ruby
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
type: [:instance, :class]
|
|
760
|
-
|
|
761
|
-
# GOOD
|
|
762
|
-
enum :color, [:red, :blue]
|
|
763
|
-
enum :type, [:instance, :class]
|
|
700
|
+
Post.async_count
|
|
701
|
+
ActiveSupport::Notifications.subscribed(->(*) { "Will never reach here" }) do
|
|
702
|
+
Post.count
|
|
764
703
|
end
|
|
765
704
|
```
|
|
766
705
|
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
When set, validates that the timestamp prefix for a migration is no more than a day ahead of
|
|
772
|
-
the timestamp associated with the current time. This is designed to prevent migrations prefixes
|
|
773
|
-
from being hand-edited to future timestamps, which impacts migration generation and other
|
|
774
|
-
migration commands.
|
|
775
|
-
|
|
776
|
-
*Adrianna Chang*
|
|
777
|
-
|
|
778
|
-
* Properly synchronize `Mysql2Adapter#active?` and `TrilogyAdapter#active?`.
|
|
779
|
-
|
|
780
|
-
As well as `disconnect!` and `verify!`.
|
|
781
|
-
|
|
782
|
-
This generally isn't a big problem as connections must not be shared between
|
|
783
|
-
threads, but is required when running transactional tests or system tests
|
|
784
|
-
and could lead to a SEGV.
|
|
785
|
-
|
|
786
|
-
*Jean Boussier*
|
|
706
|
+
In rare circumstances and under the right race condition, Active Support notifications
|
|
707
|
+
would no longer be dispatched after using an asynchronous query.
|
|
708
|
+
This is now fixed.
|
|
787
709
|
|
|
788
|
-
*
|
|
710
|
+
*Edouard Chin*
|
|
789
711
|
|
|
790
|
-
|
|
791
|
-
config.active_record.query_log_tags << :source_location
|
|
792
|
-
```
|
|
712
|
+
* Eliminate queries loading dumped schema cache on Postgres
|
|
793
713
|
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
*fatkodima*
|
|
714
|
+
Improve resiliency by avoiding needing to open a database connection to load the
|
|
715
|
+
type map while defining attribute methods at boot when a schema cache file is
|
|
716
|
+
configured on PostgreSQL databases.
|
|
799
717
|
|
|
800
|
-
*
|
|
718
|
+
*James Coleman*
|
|
801
719
|
|
|
802
|
-
|
|
720
|
+
* `ActiveRecord::Coder::JSON` can be instantiated
|
|
803
721
|
|
|
722
|
+
Options can now be passed to `ActiveRecord::Coder::JSON` when instantiating the coder. This allows:
|
|
804
723
|
```ruby
|
|
805
|
-
|
|
806
|
-
encrypts :name, encryptor: ActiveRecord::Encryption::Encryptor.new(compress: false)
|
|
807
|
-
end
|
|
724
|
+
serialize :config, coder: ActiveRecord::Coder::JSON.new(symbolize_names: true)
|
|
808
725
|
```
|
|
726
|
+
*matthaigh27*
|
|
809
727
|
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
* Deprecate passing strings to `ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename`.
|
|
813
|
-
|
|
814
|
-
A `ActiveRecord::DatabaseConfigurations::DatabaseConfig` object should be passed instead.
|
|
815
|
-
|
|
816
|
-
*Rafael Mendonça França*
|
|
817
|
-
|
|
818
|
-
* Add `row_count` field to `sql.active_record` notification.
|
|
819
|
-
|
|
820
|
-
This field returns the amount of rows returned by the query that emitted the notification.
|
|
821
|
-
|
|
822
|
-
This metric is useful in cases where one wants to detect queries with big result sets.
|
|
823
|
-
|
|
824
|
-
*Marvin Bitterlich*
|
|
825
|
-
|
|
826
|
-
* Consistently raise an `ArgumentError` when passing an invalid argument to a nested attributes association writer.
|
|
827
|
-
|
|
828
|
-
Previously, this would only raise on collection associations and produce a generic error on singular associations.
|
|
829
|
-
|
|
830
|
-
Now, it will raise on both collection and singular associations.
|
|
831
|
-
|
|
832
|
-
*Joshua Young*
|
|
833
|
-
|
|
834
|
-
* Fix single quote escapes on default generated MySQL columns.
|
|
728
|
+
* Deprecate using `insert_all`/`upsert_all` with unpersisted records in associations.
|
|
835
729
|
|
|
836
|
-
|
|
730
|
+
Using these methods on associations containing unpersisted records will now
|
|
731
|
+
show a deprecation warning, as the unpersisted records will be lost after
|
|
732
|
+
the operation.
|
|
837
733
|
|
|
838
|
-
|
|
734
|
+
*Nick Schwaderer*
|
|
839
735
|
|
|
840
|
-
|
|
736
|
+
* Make column name optional for `index_exists?`.
|
|
841
737
|
|
|
842
|
-
|
|
738
|
+
This aligns well with `remove_index` signature as well, where
|
|
739
|
+
index name doesn't need to be derived from the column names.
|
|
843
740
|
|
|
844
|
-
*
|
|
741
|
+
*Ali Ismayiliov*
|
|
845
742
|
|
|
846
|
-
*
|
|
847
|
-
|
|
743
|
+
* Change the payload name of `sql.active_record` notification for eager
|
|
744
|
+
loading from "SQL" to "#{model.name} Eager Load".
|
|
848
745
|
|
|
849
|
-
*
|
|
746
|
+
*zzak*
|
|
850
747
|
|
|
851
|
-
*
|
|
748
|
+
* Enable automatically retrying idempotent `#exists?` queries on connection
|
|
749
|
+
errors.
|
|
852
750
|
|
|
853
|
-
*
|
|
751
|
+
*Hartley McGuire*, *classidied*
|
|
854
752
|
|
|
855
|
-
*
|
|
753
|
+
* Deprecate usage of unsupported methods in conjunction with `update_all`:
|
|
856
754
|
|
|
857
|
-
|
|
755
|
+
`update_all` will now print a deprecation message if a query includes either `WITH`,
|
|
756
|
+
`WITH RECURSIVE` or `DISTINCT` statements. Those were never supported and were ignored
|
|
757
|
+
when generating the SQL query.
|
|
858
758
|
|
|
859
|
-
|
|
860
|
-
|
|
759
|
+
An error will be raised in a future Rails release. This behavior will be consistent
|
|
760
|
+
with `delete_all` which currently raises an error for unsupported statements.
|
|
861
761
|
|
|
862
|
-
*
|
|
762
|
+
*Edouard Chin*
|
|
863
763
|
|
|
864
|
-
*
|
|
764
|
+
* The table columns inside `schema.rb` are now sorted alphabetically.
|
|
865
765
|
|
|
866
|
-
|
|
867
|
-
|
|
766
|
+
Previously they'd be sorted by creation order, which can cause merge conflicts when two
|
|
767
|
+
branches modify the same table concurrently.
|
|
868
768
|
|
|
869
|
-
*
|
|
769
|
+
*John Duff*
|
|
870
770
|
|
|
871
|
-
*
|
|
771
|
+
* Introduce versions formatter for the schema dumper.
|
|
872
772
|
|
|
873
|
-
|
|
773
|
+
It is now possible to override how schema dumper formats versions information inside the
|
|
774
|
+
`structure.sql` file. Currently, the versions are simply sorted in the decreasing order.
|
|
775
|
+
Within large teams, this can potentially cause many merge conflicts near the top of the list.
|
|
874
776
|
|
|
875
|
-
Now, the
|
|
777
|
+
Now, the custom formatter can be provided with a custom sorting logic (e.g. by hash values
|
|
778
|
+
of the versions), which can greatly reduce the number of conflicts.
|
|
876
779
|
|
|
877
|
-
|
|
780
|
+
*fatkodima*
|
|
878
781
|
|
|
879
|
-
|
|
782
|
+
* Serialized attributes can now be marked as comparable.
|
|
880
783
|
|
|
881
|
-
|
|
784
|
+
A not rare issue when working with serialized attributes is that the serialized representation of an object
|
|
785
|
+
can change over time. Either because you are migrating from one serializer to the other (e.g. YAML to JSON or to msgpack),
|
|
786
|
+
or because the serializer used subtly changed its output.
|
|
882
787
|
|
|
883
|
-
|
|
788
|
+
One example is libyaml that used to have some extra trailing whitespaces, and recently fixed that.
|
|
789
|
+
When this sorts of thing happen, you end up with lots of records that report being changed even though
|
|
790
|
+
they aren't, which in the best case leads to a lot more writes to the database and in the worst case lead to nasty bugs.
|
|
884
791
|
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
new methods run `EXPLAIN` on the corresponding queries:
|
|
792
|
+
The solution is to instead compare the deserialized representation of the object, however Active Record
|
|
793
|
+
can't assume the deserialized object has a working `==` method. Hence why this new functionality is opt-in.
|
|
888
794
|
|
|
889
795
|
```ruby
|
|
890
|
-
|
|
891
|
-
# EXPLAIN SELECT COUNT(*) FROM `users`
|
|
892
|
-
# ...
|
|
893
|
-
|
|
894
|
-
User.all.explain.maximum(:id)
|
|
895
|
-
# EXPLAIN SELECT MAX(`users`.`id`) FROM `users`
|
|
896
|
-
# ...
|
|
897
|
-
```
|
|
898
|
-
|
|
899
|
-
*Petrik de Heus*
|
|
900
|
-
|
|
901
|
-
* Fixes an issue where `validates_associated` `:on` option wasn't respected
|
|
902
|
-
when validating associated records.
|
|
903
|
-
|
|
904
|
-
*Austen Madden*, *Alex Ghiculescu*, *Rafał Brize*
|
|
905
|
-
|
|
906
|
-
* Allow overriding SQLite defaults from `database.yml`.
|
|
907
|
-
|
|
908
|
-
Any PRAGMA configuration set under the `pragmas` key in the configuration
|
|
909
|
-
file takes precedence over Rails' defaults, and additional PRAGMAs can be
|
|
910
|
-
set as well.
|
|
911
|
-
|
|
912
|
-
```yaml
|
|
913
|
-
database: storage/development.sqlite3
|
|
914
|
-
timeout: 5000
|
|
915
|
-
pragmas:
|
|
916
|
-
journal_mode: off
|
|
917
|
-
temp_store: memory
|
|
796
|
+
serialize :config, type: Hash, coder: JSON, comparable: true
|
|
918
797
|
```
|
|
919
798
|
|
|
920
|
-
*
|
|
921
|
-
|
|
922
|
-
* Remove warning message when running SQLite in production, but leave it unconfigured.
|
|
923
|
-
|
|
924
|
-
There are valid use cases for running SQLite in production. However, it must be done
|
|
925
|
-
with care, so instead of a warning most users won't see anyway, it's preferable to
|
|
926
|
-
leave the configuration commented out to force them to think about having the database
|
|
927
|
-
on a persistent volume etc.
|
|
928
|
-
|
|
929
|
-
*Jacopo Beschi*, *Jean Boussier*
|
|
930
|
-
|
|
931
|
-
* Add support for generated columns to the SQLite3 adapter.
|
|
932
|
-
|
|
933
|
-
Generated columns (both stored and dynamic) are supported since version 3.31.0 of SQLite.
|
|
934
|
-
This adds support for those to the SQLite3 adapter.
|
|
799
|
+
*Jean Boussier*
|
|
935
800
|
|
|
936
|
-
|
|
937
|
-
create_table :users do |t|
|
|
938
|
-
t.string :name
|
|
939
|
-
t.virtual :name_upper, type: :string, as: 'UPPER(name)'
|
|
940
|
-
t.virtual :name_lower, type: :string, as: 'LOWER(name)', stored: true
|
|
941
|
-
end
|
|
942
|
-
```
|
|
801
|
+
* Fix MySQL default functions getting dropped when changing a column's nullability.
|
|
943
802
|
|
|
944
|
-
*
|
|
803
|
+
*Bastian Bartmann*
|
|
945
804
|
|
|
946
|
-
*
|
|
805
|
+
* SQLite extensions can be configured in `config/database.yml`.
|
|
947
806
|
|
|
948
|
-
|
|
807
|
+
The database configuration option `extensions:` allows an application to load SQLite extensions
|
|
808
|
+
when using `sqlite3` >= v2.4.0. The array members may be filesystem paths or the names of
|
|
809
|
+
modules that respond to `.to_path`:
|
|
949
810
|
|
|
950
|
-
```
|
|
951
|
-
|
|
811
|
+
``` yaml
|
|
812
|
+
development:
|
|
813
|
+
adapter: sqlite3
|
|
814
|
+
extensions:
|
|
815
|
+
- SQLean::UUID # module name responding to `.to_path`
|
|
816
|
+
- .sqlpkg/nalgeon/crypto/crypto.so # or a filesystem path
|
|
817
|
+
- <%= AppExtensions.location %> # or ruby code returning a path
|
|
952
818
|
```
|
|
953
819
|
|
|
954
|
-
*
|
|
820
|
+
*Mike Dalessio*
|
|
955
821
|
|
|
956
|
-
*
|
|
957
|
-
`assert_no_queries_match` assertions public.
|
|
822
|
+
* `ActiveRecord::Middleware::ShardSelector` supports granular database connection switching.
|
|
958
823
|
|
|
959
|
-
|
|
960
|
-
`
|
|
961
|
-
|
|
824
|
+
A new configuration option, `class_name:`, is introduced to
|
|
825
|
+
`config.active_record.shard_selector` to allow an application to specify the abstract connection
|
|
826
|
+
class to be switched by the shard selection middleware. The default class is
|
|
827
|
+
`ActiveRecord::Base`.
|
|
962
828
|
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
test "queries are made" do
|
|
966
|
-
assert_queries_count(1) { Article.first }
|
|
967
|
-
end
|
|
829
|
+
For example, this configuration tells `ShardSelector` to switch shards using
|
|
830
|
+
`AnimalsRecord.connected_to`:
|
|
968
831
|
|
|
969
|
-
test "creates a foreign key" do
|
|
970
|
-
assert_queries_match(/ADD FOREIGN KEY/i, include_schema: true) do
|
|
971
|
-
@connection.add_foreign_key(:comments, :posts)
|
|
972
|
-
end
|
|
973
|
-
end
|
|
974
|
-
end
|
|
975
832
|
```
|
|
976
|
-
|
|
977
|
-
*Petrik de Heus*, *fatkodima*
|
|
978
|
-
|
|
979
|
-
* Fix `has_secure_token` calls the setter method on initialize.
|
|
980
|
-
|
|
981
|
-
*Abeid Ahmed*
|
|
982
|
-
|
|
983
|
-
* When using a `DATABASE_URL`, allow for a configuration to map the protocol in the URL to a specific database
|
|
984
|
-
adapter. This allows decoupling the adapter the application chooses to use from the database connection details
|
|
985
|
-
set in the deployment environment.
|
|
986
|
-
|
|
987
|
-
```ruby
|
|
988
|
-
# ENV['DATABASE_URL'] = "mysql://localhost/example_database"
|
|
989
|
-
config.active_record.protocol_adapters.mysql = "trilogy"
|
|
990
|
-
# will connect to MySQL using the trilogy adapter
|
|
833
|
+
config.active_record.shard_selector = { class_name: "AnimalsRecord" }
|
|
991
834
|
```
|
|
992
835
|
|
|
993
|
-
*
|
|
836
|
+
*Mike Dalessio*
|
|
994
837
|
|
|
995
|
-
*
|
|
996
|
-
the `SHOW WARNINGS` query is executed, `ActiveRecord.db_warnings_action` proc will still be
|
|
997
|
-
called with a generic warning message rather than silently ignoring the warning(s).
|
|
838
|
+
* Reset relations after `insert_all`/`upsert_all`.
|
|
998
839
|
|
|
999
|
-
|
|
840
|
+
Bulk insert/upsert methods will now call `reset` if used on a relation, matching the behavior of `update_all`.
|
|
1000
841
|
|
|
1001
|
-
*
|
|
842
|
+
*Milo Winningham*
|
|
1002
843
|
|
|
1003
|
-
|
|
844
|
+
* Use `_N` as a parallel tests databases suffixes
|
|
1004
845
|
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
column).
|
|
846
|
+
Peviously, `-N` was used as a suffix. This can cause problems for RDBMSes
|
|
847
|
+
which do not support dashes in database names.
|
|
1008
848
|
|
|
1009
|
-
*
|
|
849
|
+
*fatkodima*
|
|
1010
850
|
|
|
1011
|
-
*
|
|
851
|
+
* Remember when a database connection has recently been verified (for
|
|
852
|
+
two seconds, by default), to avoid repeated reverifications during a
|
|
853
|
+
single request.
|
|
1012
854
|
|
|
1013
|
-
|
|
855
|
+
This should recreate a similar rate of verification as in Rails 7.1,
|
|
856
|
+
where connections are leased for the duration of a request, and thus
|
|
857
|
+
only verified once.
|
|
1014
858
|
|
|
1015
|
-
|
|
1016
|
-
Post.first.inspect #=> "#<Post id: 1>"
|
|
1017
|
-
```
|
|
859
|
+
*Matthew Draper*
|
|
1018
860
|
|
|
1019
|
-
|
|
1020
|
-
`ActiveRecord::Core#attributes_for_inspect`.
|
|
861
|
+
* Allow to reset cache counters for multiple records.
|
|
1021
862
|
|
|
1022
|
-
```ruby
|
|
1023
|
-
Post.attributes_for_inspect = [:id, :title]
|
|
1024
|
-
Post.first.inspect #=> "#<Post id: 1, title: "Hello, World!">"
|
|
1025
863
|
```
|
|
1026
|
-
|
|
1027
|
-
With `attributes_for_inspect` set to `:all`, `inspect` will list all the record's attributes.
|
|
1028
|
-
|
|
1029
|
-
```ruby
|
|
1030
|
-
Post.attributes_for_inspect = :all
|
|
1031
|
-
Post.first.inspect #=> "#<Post id: 1, title: "Hello, World!", published_at: "2023-10-23 14:28:11 +0000">"
|
|
864
|
+
Aircraft.reset_counters([1, 2, 3], :wheels_count)
|
|
1032
865
|
```
|
|
1033
866
|
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
You can also call `full_inspect` to get an inspection with all the attributes.
|
|
867
|
+
It produces much fewer queries compared to the custom implementation using looping over ids.
|
|
868
|
+
Previously: `O(ids.size * counters.size)` queries, now: `O(ids.size + counters.size)` queries.
|
|
1037
869
|
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
*Andrew Novoselac*
|
|
1041
|
-
|
|
1042
|
-
* Don't mark attributes as changed when reassigned to `Float::INFINITY` or
|
|
1043
|
-
`-Float::INFINITY`.
|
|
1044
|
-
|
|
1045
|
-
*Maicol Bentancor*
|
|
870
|
+
*fatkodima*
|
|
1046
871
|
|
|
1047
|
-
*
|
|
872
|
+
* Add `affected_rows` to `sql.active_record` Notification.
|
|
1048
873
|
|
|
1049
|
-
*
|
|
874
|
+
*Hartley McGuire*
|
|
1050
875
|
|
|
1051
|
-
*
|
|
876
|
+
* Fix `sum` when performing a grouped calculation.
|
|
1052
877
|
|
|
1053
|
-
|
|
878
|
+
`User.group(:friendly).sum` no longer worked. This is fixed.
|
|
1054
879
|
|
|
1055
|
-
|
|
1056
|
-
add_reference :person, :alias, foreign_key: { deferrable: :deferred }
|
|
1057
|
-
add_reference :alias, :person, foreign_key: { deferrable: :deferred }
|
|
1058
|
-
```
|
|
880
|
+
*Edouard Chin*
|
|
1059
881
|
|
|
1060
|
-
|
|
882
|
+
* Add support for enabling or disabling transactional tests per database.
|
|
1061
883
|
|
|
1062
|
-
|
|
884
|
+
A test class can now override the default `use_transactional_tests` setting
|
|
885
|
+
for individual databases, which can be useful if some databases need their
|
|
886
|
+
current state to be accessible to an external process while tests are running.
|
|
1063
887
|
|
|
1064
888
|
```ruby
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
Post.connection.set_constraints(:deferred)
|
|
1069
|
-
p = Post.create!(user_id: -1)
|
|
1070
|
-
u = User.create!
|
|
1071
|
-
p.user = u
|
|
1072
|
-
p.save!
|
|
889
|
+
class MostlyTransactionalTest < ActiveSupport::TestCase
|
|
890
|
+
self.use_transactional_tests = true
|
|
891
|
+
skip_transactional_tests_for_database :shared
|
|
1073
892
|
end
|
|
1074
893
|
```
|
|
1075
894
|
|
|
1076
|
-
*
|
|
1077
|
-
|
|
1078
|
-
* Include `ActiveModel::API` in `ActiveRecord::Base`.
|
|
1079
|
-
|
|
1080
|
-
*Sean Doyle*
|
|
1081
|
-
|
|
1082
|
-
* Ensure `#signed_id` outputs `url_safe` strings.
|
|
895
|
+
*Matthew Cheetham*, *Morgan Mareve*
|
|
1083
896
|
|
|
1084
|
-
|
|
897
|
+
* Cast `query_cache` value when using URL configuration.
|
|
1085
898
|
|
|
1086
|
-
*
|
|
899
|
+
*zzak*
|
|
1087
900
|
|
|
1088
|
-
|
|
901
|
+
* NULLS NOT DISTINCT works with UNIQUE CONSTRAINT as well as UNIQUE INDEX.
|
|
1089
902
|
|
|
1090
|
-
*
|
|
903
|
+
*Ryuta Kamizono*
|
|
1091
904
|
|
|
1092
|
-
|
|
1093
|
-
Topic.includes(:posts).order(posts: { created_at: :desc })
|
|
1094
|
-
```
|
|
905
|
+
* `PG::UnableToSend: no connection to the server` is now retryable as a connection-related exception
|
|
1095
906
|
|
|
1096
|
-
*
|
|
907
|
+
*Kazuma Watanabe*
|
|
1097
908
|
|
|
1098
|
-
Please check [
|
|
909
|
+
Please check [8-0-stable](https://github.com/rails/rails/blob/8-0-stable/activerecord/CHANGELOG.md) for previous changes.
|