activerecord 8.0.2.1 → 8.1.0.beta1
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 +459 -421
- data/README.rdoc +2 -2
- data/lib/active_record/association_relation.rb +1 -1
- data/lib/active_record/associations/association.rb +1 -1
- data/lib/active_record/associations/belongs_to_association.rb +9 -1
- data/lib/active_record/associations/builder/association.rb +16 -5
- 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 +3 -3
- data/lib/active_record/associations/collection_proxy.rb +22 -4
- data/lib/active_record/associations/deprecation.rb +88 -0
- data/lib/active_record/associations/errors.rb +3 -0
- data/lib/active_record/associations/join_dependency.rb +2 -0
- data/lib/active_record/associations/preloader/branch.rb +1 -0
- data/lib/active_record/associations.rb +159 -21
- data/lib/active_record/attribute_methods/query.rb +34 -0
- data/lib/active_record/attribute_methods/serialization.rb +17 -4
- data/lib/active_record/attributes.rb +38 -24
- data/lib/active_record/base.rb +0 -1
- data/lib/active_record/coders/json.rb +14 -5
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +2 -4
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +15 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +51 -12
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +384 -49
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +26 -30
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +19 -1
- data/lib/active_record/connection_adapters/abstract/quoting.rb +15 -24
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +7 -2
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +26 -34
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +89 -23
- data/lib/active_record/connection_adapters/abstract/transaction.rb +16 -3
- data/lib/active_record/connection_adapters/abstract_adapter.rb +67 -13
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +43 -11
- 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/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +42 -5
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +26 -4
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +27 -22
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +18 -16
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +2 -2
- 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/schema_creation.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +8 -21
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +65 -30
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +74 -38
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +12 -7
- data/lib/active_record/connection_adapters/schema_cache.rb +2 -2
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +39 -27
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +0 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +4 -13
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +56 -32
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +4 -3
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +1 -1
- data/lib/active_record/connection_adapters.rb +1 -0
- data/lib/active_record/connection_handling.rb +1 -1
- data/lib/active_record/core.rb +12 -9
- data/lib/active_record/counter_cache.rb +33 -8
- data/lib/active_record/database_configurations/database_config.rb +5 -1
- data/lib/active_record/database_configurations/hash_config.rb +56 -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 +2 -2
- data/lib/active_record/dynamic_matchers.rb +54 -69
- data/lib/active_record/encryption/encryptable_record.rb +5 -5
- data/lib/active_record/encryption/encrypted_attribute_type.rb +2 -2
- data/lib/active_record/encryption/encryptor.rb +27 -25
- data/lib/active_record/encryption/scheme.rb +1 -1
- data/lib/active_record/enum.rb +37 -20
- data/lib/active_record/errors.rb +20 -4
- data/lib/active_record/explain_registry.rb +0 -1
- 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 -2
- 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 +7 -0
- data/lib/active_record/locking/pessimistic.rb +5 -0
- data/lib/active_record/log_subscriber.rb +1 -5
- data/lib/active_record/middleware/shard_selector.rb +34 -17
- data/lib/active_record/migration/command_recorder.rb +14 -1
- data/lib/active_record/migration/compatibility.rb +34 -24
- data/lib/active_record/migration/default_schema_versions_formatter.rb +30 -0
- data/lib/active_record/migration.rb +31 -21
- data/lib/active_record/model_schema.rb +10 -7
- data/lib/active_record/nested_attributes.rb +2 -0
- data/lib/active_record/persistence.rb +34 -3
- data/lib/active_record/query_cache.rb +22 -15
- data/lib/active_record/query_logs.rb +7 -7
- data/lib/active_record/querying.rb +4 -4
- data/lib/active_record/railtie.rb +34 -5
- data/lib/active_record/railties/databases.rake +23 -19
- 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 +42 -3
- data/lib/active_record/relation/batches.rb +26 -12
- data/lib/active_record/relation/calculations.rb +35 -25
- data/lib/active_record/relation/delegation.rb +0 -1
- data/lib/active_record/relation/finder_methods.rb +37 -21
- data/lib/active_record/relation/merger.rb +2 -2
- data/lib/active_record/relation/predicate_builder.rb +2 -2
- data/lib/active_record/relation/query_attribute.rb +3 -1
- data/lib/active_record/relation/query_methods.rb +43 -33
- data/lib/active_record/relation/spawn_methods.rb +6 -6
- data/lib/active_record/relation/where_clause.rb +7 -10
- data/lib/active_record/relation.rb +37 -15
- data/lib/active_record/result.rb +44 -21
- data/lib/active_record/sanitization.rb +2 -0
- data/lib/active_record/schema_dumper.rb +12 -10
- data/lib/active_record/scoping.rb +0 -1
- data/lib/active_record/secure_token.rb +3 -3
- data/lib/active_record/signed_id.rb +46 -18
- data/lib/active_record/statement_cache.rb +13 -9
- data/lib/active_record/store.rb +44 -19
- data/lib/active_record/tasks/abstract_tasks.rb +76 -0
- data/lib/active_record/tasks/database_tasks.rb +24 -35
- data/lib/active_record/tasks/mysql_database_tasks.rb +3 -40
- data/lib/active_record/tasks/postgresql_database_tasks.rb +14 -40
- data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -26
- data/lib/active_record/test_databases.rb +11 -3
- data/lib/active_record/test_fixtures.rb +27 -2
- data/lib/active_record/testing/query_assertions.rb +8 -2
- data/lib/active_record/timestamp.rb +4 -2
- data/lib/active_record/transaction.rb +2 -5
- data/lib/active_record/transactions.rb +34 -10
- 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.rb +68 -5
- data/lib/arel/alias_predication.rb +2 -0
- data/lib/arel/crud.rb +8 -11
- data/lib/arel/delete_manager.rb +5 -0
- 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 +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/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 +5 -21
- data/lib/arel.rb +3 -1
- metadata +13 -9
- data/lib/active_record/normalization.rb +0 -163
data/CHANGELOG.md
CHANGED
@@ -1,675 +1,713 @@
|
|
1
|
-
## Rails 8.0.
|
1
|
+
## Rails 8.1.0.beta1 (September 04, 2025) ##
|
2
2
|
|
3
|
-
*
|
3
|
+
* Remove deprecated `:unsigned_float` and `:unsigned_decimal` column methods for MySQL.
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
*Gannon McGibbon*, *John Hawthorn*
|
8
|
-
|
9
|
-
## Rails 8.0.2 (March 12, 2025) ##
|
10
|
-
|
11
|
-
* No changes.
|
5
|
+
*Rafael Mendonça França*
|
12
6
|
|
7
|
+
* Remove deprecated `:retries` option for the SQLite3 adapter.
|
13
8
|
|
14
|
-
|
9
|
+
*Rafael Mendonça França*
|
15
10
|
|
16
|
-
*
|
11
|
+
* Introduce new database configuration options `keepalive`, `max_age`, and
|
12
|
+
`min_connections` -- and rename `pool` to `max_connections` to match.
|
17
13
|
|
18
|
-
|
14
|
+
There are no changes to default behavior, but these allow for more specific
|
15
|
+
control over pool behavior.
|
19
16
|
|
20
|
-
*
|
17
|
+
*Matthew Draper*, *Chris AtLee*, *Rachael Wright-Munn*
|
21
18
|
|
22
|
-
|
19
|
+
* Move `LIMIT` validation from query generation to when `limit()` is called.
|
23
20
|
|
24
|
-
*
|
21
|
+
*Hartley McGuire*, *Shuyang*
|
25
22
|
|
26
|
-
|
27
|
-
|
28
|
-
* Fix count with group by qualified name on loaded relation.
|
23
|
+
* Add `ActiveRecord::CheckViolation` error class for check constraint violations.
|
29
24
|
|
30
25
|
*Ryuta Kamizono*
|
31
26
|
|
32
|
-
*
|
33
|
-
|
34
|
-
*Chris Gunther*
|
35
|
-
|
36
|
-
* The SQLite3 adapter quotes non-finite Numeric values like "Infinity" and "NaN".
|
37
|
-
|
38
|
-
*Mike Dalessio*
|
39
|
-
|
40
|
-
* Handle libpq returning a database version of 0 on no/bad connection in `PostgreSQLAdapter`.
|
41
|
-
|
42
|
-
Before, this version would be cached and an error would be raised during connection configuration when
|
43
|
-
comparing it with the minimum required version for the adapter. This meant that the connection could
|
44
|
-
never be successfully configured on subsequent reconnection attempts.
|
27
|
+
* Add `ActiveRecord::ExclusionViolation` error class for exclusion constraint violations.
|
45
28
|
|
46
|
-
|
47
|
-
|
29
|
+
When an exclusion constraint is violated in PostgreSQL, the error will now be raised
|
30
|
+
as `ActiveRecord::ExclusionViolation` instead of the generic `ActiveRecord::StatementInvalid`,
|
31
|
+
making it easier to handle these specific constraint violations in application code.
|
48
32
|
|
49
|
-
|
33
|
+
This follows the same pattern as other constraint violation error classes like
|
34
|
+
`RecordNotUnique` for unique constraint violations and `InvalidForeignKey` for
|
35
|
+
foreign key constraint violations.
|
50
36
|
|
51
|
-
*
|
52
|
-
|
53
|
-
Active Record wasn't properly handling errors during the connection configuration phase.
|
54
|
-
This could lead to a partially configured connection being used, resulting in various exceptions,
|
55
|
-
the most common being with the PostgreSQLAdapter raising `undefined method `key?' for nil`
|
56
|
-
or `TypeError: wrong argument type nil (expected PG::TypeMap)`.
|
57
|
-
|
58
|
-
*Jean Boussier*
|
59
|
-
|
60
|
-
* Fix a case where a non-retryable query could be marked retryable.
|
37
|
+
*Ryuta Kamizono*
|
61
38
|
|
62
|
-
|
39
|
+
* Attributes filtered by `filter_attributes` will now also be filtered by `filter_parameters`
|
40
|
+
so sensitive information is not leaked.
|
63
41
|
|
64
|
-
*
|
42
|
+
*Jill Klang*
|
65
43
|
|
66
|
-
|
44
|
+
* Add `connection.current_transaction.isolation` API to check current transaction's isolation level.
|
67
45
|
|
68
|
-
|
46
|
+
Returns the isolation level if it was explicitly set via the `isolation:` parameter
|
47
|
+
or through `ActiveRecord.with_transaction_isolation_level`, otherwise returns `nil`.
|
48
|
+
Nested transactions return the parent transaction's isolation level.
|
69
49
|
|
70
|
-
|
71
|
-
|
50
|
+
```ruby
|
51
|
+
# Returns nil when no transaction
|
52
|
+
User.connection.current_transaction.isolation # => nil
|
72
53
|
|
73
|
-
|
54
|
+
# Returns explicitly set isolation level
|
55
|
+
User.transaction(isolation: :serializable) do
|
56
|
+
User.connection.current_transaction.isolation # => :serializable
|
57
|
+
end
|
74
58
|
|
75
|
-
|
59
|
+
# Returns nil when isolation not explicitly set
|
60
|
+
User.transaction do
|
61
|
+
User.connection.current_transaction.isolation # => nil
|
62
|
+
end
|
76
63
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
64
|
+
# Nested transactions inherit parent's isolation
|
65
|
+
User.transaction(isolation: :read_committed) do
|
66
|
+
User.transaction do
|
67
|
+
User.connection.current_transaction.isolation # => :read_committed
|
68
|
+
end
|
81
69
|
end
|
82
70
|
```
|
83
71
|
|
84
|
-
|
85
|
-
would no longer be dispatched after using an asynchronous query.
|
86
|
-
This is now fixed.
|
72
|
+
*Kir Shatrov*
|
87
73
|
|
88
|
-
|
89
|
-
|
90
|
-
* Fix support for PostgreSQL enum types with commas in their name.
|
91
|
-
|
92
|
-
*Arthur Hess*
|
93
|
-
|
94
|
-
* Fix inserts on MySQL with no RETURNING support for a table with multiple auto populated columns.
|
74
|
+
* Emit a warning for pg gem < 1.6.0 when using PostgreSQL 18+
|
95
75
|
|
96
|
-
*
|
76
|
+
*Yasuo Honda*
|
97
77
|
|
98
|
-
* Fix
|
78
|
+
* Fix `#merge` with `#or` or `#and` and a mixture of attributes and SQL strings resulting in an incorrect query.
|
99
79
|
|
100
80
|
```ruby
|
101
|
-
|
102
|
-
|
103
|
-
end
|
104
|
-
|
105
|
-
class InstructorRole < ActiveRecord::Base
|
106
|
-
scope :active, -> {
|
107
|
-
joins("JOIN students ON instructor_roles.student_id = students.id")
|
108
|
-
.where(students { status: 1 })
|
109
|
-
}
|
110
|
-
end
|
111
|
-
|
112
|
-
Instructor.joins(:instructor_roles).first
|
81
|
+
base = Comment.joins(:post).where(user_id: 1).where("recent = 1")
|
82
|
+
puts base.merge(base.where(draft: true).or(Post.where(archived: true))).to_sql
|
113
83
|
```
|
114
84
|
|
115
|
-
|
116
|
-
|
85
|
+
Before:
|
86
|
+
|
87
|
+
```SQL
|
88
|
+
SELECT "comments".* FROM "comments"
|
89
|
+
INNER JOIN "posts" ON "posts"."id" = "comments"."post_id"
|
90
|
+
WHERE (recent = 1)
|
91
|
+
AND (
|
92
|
+
"comments"."user_id" = 1
|
93
|
+
AND (recent = 1)
|
94
|
+
AND "comments"."draft" = 1
|
95
|
+
OR "posts"."archived" = 1
|
96
|
+
)
|
97
|
+
```
|
117
98
|
|
118
|
-
|
99
|
+
After:
|
100
|
+
|
101
|
+
```SQL
|
102
|
+
SELECT "comments".* FROM "comments"
|
103
|
+
INNER JOIN "posts" ON "posts"."id" = "comments"."post_id"
|
104
|
+
WHERE "comments"."user_id" = 1
|
105
|
+
AND (recent = 1)
|
106
|
+
AND (
|
107
|
+
"comments"."user_id" = 1
|
108
|
+
AND (recent = 1)
|
109
|
+
AND "comments"."draft" = 1
|
110
|
+
OR "posts"."archived" = 1
|
111
|
+
)
|
112
|
+
```
|
119
113
|
|
120
|
-
*
|
114
|
+
*Joshua Young*
|
121
115
|
|
122
|
-
|
116
|
+
* Make schema dumper to account for `ActiveRecord.dump_schemas` when dumping in `:ruby` format.
|
123
117
|
|
124
|
-
*
|
118
|
+
*fatkodima*
|
125
119
|
|
126
|
-
|
127
|
-
weren't created nor modified as part of the transaction:
|
120
|
+
* Add `:touch` option to `update_column`/`update_columns` methods.
|
128
121
|
|
129
122
|
```ruby
|
130
|
-
|
131
|
-
|
123
|
+
# Will update :updated_at/:updated_on alongside :nice column.
|
124
|
+
user.update_column(:nice, true, touch: true)
|
132
125
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
two seconds, by default), to avoid repeated reverifications during a
|
137
|
-
single request.
|
138
|
-
|
139
|
-
This should recreate a similar rate of verification as in Rails 7.1,
|
140
|
-
where connections are leased for the duration of a request, and thus
|
141
|
-
only verified once.
|
126
|
+
# Will update :updated_at/:updated_on alongside :last_ip column
|
127
|
+
user.update_columns(last_ip: request.remote_ip, touch: true)
|
128
|
+
```
|
142
129
|
|
143
|
-
*
|
130
|
+
*Dmitrii Ivliev*
|
144
131
|
|
132
|
+
* Optimize Active Record batching further when using ranges.
|
145
133
|
|
146
|
-
|
134
|
+
Tested on a PostgreSQL table with 10M records and batches of 10k records, the generation
|
135
|
+
of relations for the 1000 batches was `4.8x` faster (`6.8s` vs. `1.4s`), used `900x`
|
136
|
+
less bandwidth (`180MB` vs. `0.2MB`) and allocated `45x` less memory (`490MB` vs. `11MB`).
|
147
137
|
|
148
|
-
*
|
138
|
+
*Maxime Réty*, *fatkodima*
|
149
139
|
|
150
|
-
|
140
|
+
* Include current character length in error messages for index and table name length validations.
|
151
141
|
|
152
|
-
*
|
142
|
+
*Joshua Young*
|
153
143
|
|
154
|
-
|
155
|
-
it could result in a `NoMethodError` being raised.
|
144
|
+
* Add `rename_schema` method for PostgreSQL.
|
156
145
|
|
157
|
-
*
|
146
|
+
*T S Vallender*
|
158
147
|
|
159
|
-
*
|
148
|
+
* Implement support for deprecating associations:
|
160
149
|
|
161
|
-
|
150
|
+
```ruby
|
151
|
+
has_many :posts, deprecated: true
|
152
|
+
```
|
162
153
|
|
163
|
-
|
154
|
+
With that, Active Record will report any usage of the `posts` association.
|
164
155
|
|
165
|
-
|
156
|
+
Three reporting modes are supported (`:warn`, `:raise`, and `:notify`), and
|
157
|
+
backtraces can be enabled or disabled. Defaults are `:warn` mode and
|
158
|
+
disabled backtraces.
|
166
159
|
|
167
|
-
|
160
|
+
Please, check the docs for further details.
|
168
161
|
|
169
|
-
*
|
162
|
+
*Xavier Noria*
|
170
163
|
|
171
|
-
*
|
164
|
+
* PostgreSQL adapter create DB now supports `locale_provider` and `locale`.
|
172
165
|
|
173
|
-
*
|
166
|
+
*Bengt-Ove Hollaender*
|
174
167
|
|
175
|
-
*
|
168
|
+
* Use ntuples to populate row_count instead of count for Postgres
|
176
169
|
|
177
|
-
*
|
170
|
+
*Jonathan Calvert*
|
178
171
|
|
179
|
-
* Fix
|
172
|
+
* Fix checking whether an unpersisted record is `include?`d in a strictly
|
173
|
+
loaded `has_and_belongs_to_many` association.
|
180
174
|
|
181
|
-
*
|
175
|
+
*Hartley McGuire*
|
182
176
|
|
183
|
-
*
|
177
|
+
* Add ability to change transaction isolation for all pools within a block.
|
184
178
|
|
185
|
-
|
179
|
+
This functionality is useful if your application needs to change the database
|
180
|
+
transaction isolation for a request or action.
|
186
181
|
|
187
|
-
|
182
|
+
Calling `ActiveRecord.with_transaction_isolation_level(level) {}` in an around filter or
|
183
|
+
middleware will set the transaction isolation for all pools accessed within the block,
|
184
|
+
but not for the pools that aren't.
|
188
185
|
|
189
|
-
|
186
|
+
This works with explicit and implicit transactions:
|
190
187
|
|
191
|
-
|
188
|
+
```ruby
|
189
|
+
ActiveRecord.with_transaction_isolation_level(:read_committed) do
|
190
|
+
Tag.transaction do # opens a transaction explicitly
|
191
|
+
Tag.create!
|
192
|
+
end
|
193
|
+
end
|
194
|
+
```
|
192
195
|
|
193
|
-
|
196
|
+
```ruby
|
197
|
+
ActiveRecord.with_transaction_isolation_level(:read_committed) do
|
198
|
+
Tag.create! # opens a transaction implicitly
|
199
|
+
end
|
200
|
+
```
|
194
201
|
|
195
|
-
*
|
202
|
+
*Eileen M. Uchitelle*
|
196
203
|
|
197
|
-
*
|
204
|
+
* Raise `ActiveRecord::MissingRequiredOrderError` when order dependent finder methods (e.g. `#first`, `#last`) are
|
205
|
+
called without `order` values on the relation, and the model does not have any order columns (`implicit_order_column`,
|
206
|
+
`query_constraints`, or `primary_key`) to fall back on.
|
198
207
|
|
199
|
-
|
208
|
+
This change will be introduced with a new framework default for Rails 8.1, and the current behavior of not raising
|
209
|
+
an error has been deprecated with the aim of removing the configuration option in Rails 8.2.
|
200
210
|
|
201
|
-
|
211
|
+
```ruby
|
212
|
+
config.active_record.raise_on_missing_required_finder_order_columns = true
|
213
|
+
```
|
202
214
|
|
203
215
|
*Joshua Young*
|
204
216
|
|
205
|
-
*
|
217
|
+
* `:class_name` is now invalid in polymorphic `belongs_to` associations.
|
206
218
|
|
207
|
-
`
|
219
|
+
Reason is `:class_name` does not make sense in those associations because
|
220
|
+
the class name of target records is dynamic and stored in the type column.
|
208
221
|
|
209
|
-
|
222
|
+
Existing polymorphic associations setting this option can just delete it.
|
223
|
+
While it did not raise, it had no effect anyway.
|
210
224
|
|
211
|
-
*
|
225
|
+
*Xavier Noria*
|
212
226
|
|
213
|
-
|
227
|
+
* Add support for multiple databases to `db:migrate:reset`.
|
214
228
|
|
229
|
+
*Joé Dupuis*
|
215
230
|
|
216
|
-
|
231
|
+
* Add `affected_rows` to `ActiveRecord::Result`.
|
217
232
|
|
218
|
-
*
|
233
|
+
*Jenny Shen*
|
219
234
|
|
235
|
+
* Enable passing retryable SqlLiterals to `#where`.
|
220
236
|
|
221
|
-
|
237
|
+
*Hartley McGuire*
|
222
238
|
|
223
|
-
*
|
239
|
+
* Set default for primary keys in `insert_all`/`upsert_all`.
|
224
240
|
|
225
|
-
|
241
|
+
Previously in Postgres, updating and inserting new records in one upsert wasn't possible
|
242
|
+
due to null primary key values. `nil` primary key values passed into `insert_all`/`upsert_all`
|
243
|
+
are now implicitly set to the default insert value specified by adapter.
|
226
244
|
|
227
|
-
*
|
245
|
+
*Jenny Shen*
|
228
246
|
|
247
|
+
* Add a load hook `active_record_database_configurations` for `ActiveRecord::DatabaseConfigurations`
|
229
248
|
|
230
|
-
|
249
|
+
*Mike Dalessio*
|
231
250
|
|
232
|
-
*
|
251
|
+
* Use `TRUE` and `FALSE` for SQLite queries with boolean columns.
|
233
252
|
|
234
|
-
*
|
253
|
+
*Hartley McGuire*
|
235
254
|
|
236
|
-
*
|
255
|
+
* Bump minimum supported SQLite to 3.23.0.
|
237
256
|
|
238
|
-
|
239
|
-
is created, leading to potential loss of data if a database is added to an
|
240
|
-
existing environment.
|
257
|
+
*Hartley McGuire*
|
241
258
|
|
242
|
-
|
243
|
-
are loaded during `db:prepare` which defaults to `true` for primary database
|
244
|
-
configs and `false` otherwise.
|
259
|
+
* Allow allocated Active Records to lookup associations.
|
245
260
|
|
246
|
-
|
261
|
+
Previously, the association cache isn't setup on allocated record objects, so association
|
262
|
+
lookups will crash. Test frameworks like mocha use allocate to check for stubbable instance
|
263
|
+
methods, which can trigger an association lookup.
|
247
264
|
|
248
|
-
*
|
265
|
+
*Gannon McGibbon*
|
249
266
|
|
250
|
-
*
|
267
|
+
* Encryption now supports `support_unencrypted_data: true` being set per-attribute.
|
251
268
|
|
252
|
-
|
269
|
+
Previously this only worked if `ActiveRecord::Encryption.config.support_unencrypted_data == true`.
|
270
|
+
Now, if the global config is turned off, you can still opt in for a specific attribute.
|
253
271
|
|
254
|
-
|
272
|
+
```ruby
|
273
|
+
# ActiveRecord::Encryption.config.support_unencrypted_data = true
|
274
|
+
class User < ActiveRecord::Base
|
275
|
+
encrypts :name, support_unencrypted_data: false # only supports encrypted data
|
276
|
+
encrypts :email # supports encrypted or unencrypted data
|
277
|
+
end
|
278
|
+
```
|
255
279
|
|
256
|
-
|
280
|
+
```ruby
|
281
|
+
# ActiveRecord::Encryption.config.support_unencrypted_data = false
|
282
|
+
class User < ActiveRecord::Base
|
283
|
+
encrypts :name, support_unencrypted_data: true # supports encrypted or unencrypted data
|
284
|
+
encrypts :email # only supports encrypted data
|
285
|
+
end
|
286
|
+
```
|
257
287
|
|
258
|
-
*
|
288
|
+
*Alex Ghiculescu*
|
259
289
|
|
260
|
-
|
290
|
+
* Model generator no longer needs a database connection to validate column types.
|
261
291
|
|
292
|
+
*Mike Dalessio*
|
262
293
|
|
263
|
-
|
294
|
+
* Allow signed ID verifiers to be configurable via `Rails.application.message_verifiers`
|
264
295
|
|
265
|
-
|
296
|
+
Prior to this change, the primary way to configure signed ID verifiers was
|
297
|
+
to set `signed_id_verifier` on each model class:
|
266
298
|
|
267
|
-
|
299
|
+
```ruby
|
300
|
+
Post.signed_id_verifier = ActiveSupport::MessageVerifier.new(...)
|
301
|
+
Comment.signed_id_verifier = ActiveSupport::MessageVerifier.new(...)
|
302
|
+
```
|
268
303
|
|
269
|
-
|
304
|
+
And if the developer did not set `signed_id_verifier`, a verifier would be
|
305
|
+
instantiated with a secret derived from `secret_key_base` and the following
|
306
|
+
options:
|
270
307
|
|
271
|
-
|
308
|
+
```ruby
|
309
|
+
{ digest: "SHA256", serializer: JSON, url_safe: true }
|
310
|
+
```
|
272
311
|
|
273
|
-
|
312
|
+
Thus it was cumbersome to rotate configuration for all verifiers.
|
274
313
|
|
275
|
-
|
314
|
+
This change defines a new Rails config: [`config.active_record.use_legacy_signed_id_verifier`][].
|
315
|
+
The default value is `:generate_and_verify`, which preserves the previous
|
316
|
+
behavior. However, when set to `:verify`, signed ID verifiers will use
|
317
|
+
configuration from `Rails.application.message_verifiers` (specifically,
|
318
|
+
`Rails.application.message_verifiers["active_record/signed_id"]`) to
|
319
|
+
generate and verify signed IDs, but will also verify signed IDs using the
|
320
|
+
older configuration.
|
276
321
|
|
277
|
-
|
322
|
+
To avoid complication, the new behavior only applies when `signed_id_verifier_secret`
|
323
|
+
is not set on a model class or any of its ancestors. Additionally,
|
324
|
+
`signed_id_verifier_secret` is now deprecated. If you are currently setting
|
325
|
+
`signed_id_verifier_secret` on a model class, you can set `signed_id_verifier`
|
326
|
+
instead:
|
278
327
|
|
279
|
-
|
328
|
+
```ruby
|
329
|
+
# BEFORE
|
330
|
+
Post.signed_id_verifier_secret = "my secret"
|
280
331
|
|
281
|
-
|
332
|
+
# AFTER
|
333
|
+
Post.signed_id_verifier = ActiveSupport::MessageVerifier.new("my secret", digest: "SHA256", serializer: JSON, url_safe: true)
|
334
|
+
```
|
282
335
|
|
283
|
-
|
336
|
+
To ease migration, `signed_id_verifier` has also been changed to behave as a
|
337
|
+
`class_attribute` (i.e. inheritable), but _only when `signed_id_verifier_secret`
|
338
|
+
is not set_:
|
284
339
|
|
285
|
-
|
340
|
+
```ruby
|
341
|
+
# BEFORE
|
342
|
+
ActiveRecord::Base.signed_id_verifier = ActiveSupport::MessageVerifier.new(...)
|
343
|
+
Post.signed_id_verifier == ActiveRecord::Base.signed_id_verifier # => false
|
286
344
|
|
287
|
-
|
345
|
+
# AFTER
|
346
|
+
ActiveRecord::Base.signed_id_verifier = ActiveSupport::MessageVerifier.new(...)
|
347
|
+
Post.signed_id_verifier == ActiveRecord::Base.signed_id_verifier # => true
|
288
348
|
|
289
|
-
|
349
|
+
Post.signed_id_verifier_secret = "my secret" # => deprecation warning
|
350
|
+
Post.signed_id_verifier == ActiveRecord::Base.signed_id_verifier # => false
|
351
|
+
```
|
290
352
|
|
291
|
-
|
353
|
+
Note, however, that it is recommended to eventually migrate from
|
354
|
+
model-specific verifiers to a unified configuration managed by
|
355
|
+
`Rails.application.message_verifiers`. `ActiveSupport::MessageVerifier#rotate`
|
356
|
+
can facilitate that transition. For example:
|
292
357
|
|
293
|
-
|
358
|
+
```ruby
|
359
|
+
# BEFORE
|
360
|
+
# Generate and verify signed Post IDs using Post-specific configuration
|
361
|
+
Post.signed_id_verifier = ActiveSupport::MessageVerifier.new("post secret", ...)
|
294
362
|
|
295
|
-
|
363
|
+
# AFTER
|
364
|
+
# Generate and verify signed Post IDs using the unified configuration
|
365
|
+
Post.signed_id_verifier = Post.signed_id_verifier.dup
|
366
|
+
# Fall back to Post-specific configuration when verifying signed IDs
|
367
|
+
Post.signed_id_verifier.rotate("post secret", ...)
|
368
|
+
```
|
296
369
|
|
297
|
-
|
370
|
+
[`config.active_record.use_legacy_signed_id_verifier`]: https://guides.rubyonrails.org/v8.1/configuring.html#config-active-record-use-legacy-signed-id-verifier
|
298
371
|
|
299
|
-
*
|
372
|
+
*Ali Sepehri*, *Jonathan Hefner*
|
300
373
|
|
301
|
-
*
|
374
|
+
* Prepend `extra_flags` in postgres' `structure_load`
|
302
375
|
|
303
|
-
|
376
|
+
When specifying `structure_load_flags` with a postgres adapter, the flags
|
377
|
+
were appended to the default flags, instead of prepended.
|
378
|
+
This caused issues with flags not being taken into account by postgres.
|
304
379
|
|
305
|
-
*
|
306
|
-
specified.
|
380
|
+
*Alice Loeser*
|
307
381
|
|
308
|
-
|
382
|
+
* Allow bypassing primary key/constraint addition in `implicit_order_column`
|
309
383
|
|
310
|
-
|
384
|
+
When specifying multiple columns in an array for `implicit_order_column`, adding
|
385
|
+
`nil` as the last element will prevent appending the primary key to order
|
386
|
+
conditions. This allows more precise control of indexes used by
|
387
|
+
generated queries. It should be noted that this feature does introduce the risk
|
388
|
+
of API misbehavior if the specified columns are not fully unique.
|
311
389
|
|
312
|
-
*
|
390
|
+
*Issy Long*
|
313
391
|
|
314
|
-
* Allow `
|
392
|
+
* Allow setting the `schema_format` via database configuration.
|
315
393
|
|
316
|
-
```
|
317
|
-
|
318
|
-
|
394
|
+
```
|
395
|
+
primary:
|
396
|
+
schema_format: ruby
|
319
397
|
```
|
320
398
|
|
321
|
-
|
322
|
-
|
323
|
-
* Make Float distinguish between `float4` and `float8` in PostgreSQL.
|
324
|
-
|
325
|
-
Fixes #52742
|
399
|
+
Useful for multi-database setups when apps require different formats per-database.
|
326
400
|
|
327
|
-
*
|
401
|
+
*T S Vallender*
|
328
402
|
|
403
|
+
* Support disabling indexes for MySQL v8.0.0+ and MariaDB v10.6.0+
|
329
404
|
|
330
|
-
|
405
|
+
MySQL 8.0.0 added an option to disable indexes from being used by the query
|
406
|
+
optimizer by making them "invisible". This allows the index to still be maintained
|
407
|
+
and updated but no queries will be permitted to use it. This can be useful for adding
|
408
|
+
new invisible indexes or making existing indexes invisible before dropping them
|
409
|
+
to ensure queries are not negatively affected.
|
410
|
+
See https://dev.mysql.com/blog-archive/mysql-8-0-invisible-indexes/ for more details.
|
331
411
|
|
332
|
-
|
412
|
+
MariaDB 10.6.0 also added support for this feature by allowing indexes to be "ignored"
|
413
|
+
in queries. See https://mariadb.com/kb/en/ignored-indexes/ for more details.
|
333
414
|
|
334
|
-
|
415
|
+
Active Record now supports this option for MySQL 8.0.0+ and MariaDB 10.6.0+ for
|
416
|
+
index creation and alteration where the new index option `enabled: true/false` can be
|
417
|
+
passed to column and index methods as below:
|
335
418
|
|
336
419
|
```ruby
|
337
|
-
|
420
|
+
add_index :users, :email, enabled: false
|
421
|
+
enable_index :users, :email
|
422
|
+
add_column :users, :dob, :string, index: { enabled: false }
|
423
|
+
|
424
|
+
change_table :users do |t|
|
425
|
+
t.index :name, enabled: false
|
426
|
+
t.index :dob
|
427
|
+
t.disable_index :dob
|
428
|
+
t.column :username, :string, index: { enabled: false }
|
429
|
+
t.references :account, index: { enabled: false }
|
430
|
+
end
|
431
|
+
|
432
|
+
create_table :users do |t|
|
433
|
+
t.string :name, index: { enabled: false }
|
434
|
+
t.string :email
|
435
|
+
t.index :email, enabled: false
|
436
|
+
end
|
338
437
|
```
|
339
438
|
|
340
|
-
*
|
439
|
+
*Merve Taner*
|
341
440
|
|
342
|
-
*
|
343
|
-
on the `add_enum_value` method.
|
441
|
+
* Respect `implicit_order_column` in `ActiveRecord::Relation#reverse_order`.
|
344
442
|
|
345
|
-
*
|
443
|
+
*Joshua Young*
|
346
444
|
|
347
|
-
*
|
445
|
+
* Add column types to `ActiveRecord::Result` for SQLite3.
|
348
446
|
|
349
|
-
*Andrew
|
447
|
+
*Andrew Kane*
|
350
448
|
|
351
|
-
*
|
352
|
-
the same child association but different parents does not join all parents.
|
449
|
+
* Raise `ActiveRecord::ReadOnlyError` when pessimistically locking with a readonly role.
|
353
450
|
|
354
|
-
|
451
|
+
*Joshua Young*
|
355
452
|
|
356
|
-
|
453
|
+
* Fix using the `SQLite3Adapter`'s `dbconsole` method outside of a Rails application.
|
357
454
|
|
358
|
-
|
455
|
+
*Hartley McGuire*
|
359
456
|
|
360
|
-
|
457
|
+
* Fix migrating multiple databases with `ActiveRecord::PendingMigration` action.
|
361
458
|
|
362
|
-
*
|
459
|
+
*Gannon McGibbon*
|
363
460
|
|
364
|
-
|
365
|
-
|
461
|
+
* Enable automatically retrying idempotent association queries on connection
|
462
|
+
errors.
|
366
463
|
|
367
|
-
|
464
|
+
*Hartley McGuire*
|
368
465
|
|
369
|
-
|
466
|
+
* Add `allow_retry` to `sql.active_record` instrumentation.
|
370
467
|
|
371
|
-
|
468
|
+
This enables identifying queries which queries are automatically retryable on connection errors.
|
372
469
|
|
373
|
-
|
374
|
-
which we have supported in the core. Now we support MySQL 5.6.4 or later, which
|
375
|
-
is the first version to support datetime with precision.
|
470
|
+
*Hartley McGuire*
|
376
471
|
|
377
|
-
|
472
|
+
* Better support UPDATE with JOIN for Postgresql and SQLite3
|
378
473
|
|
379
|
-
|
474
|
+
Previously when generating update queries with one or more JOIN clauses,
|
475
|
+
Active Record would use a sub query which would prevent to reference the joined
|
476
|
+
tables in the `SET` clause, for instance:
|
380
477
|
|
381
|
-
|
382
|
-
|
478
|
+
```ruby
|
479
|
+
Comment.joins(:post).update_all("title = posts.title")
|
480
|
+
```
|
383
481
|
|
384
|
-
|
385
|
-
|
482
|
+
This is now supported as long as the relation doesn't also use a `LIMIT`, `ORDER` or
|
483
|
+
`GROUP BY` clause. This was supported by the MySQL adapter for a long time.
|
386
484
|
|
387
485
|
*Jean Boussier*
|
388
486
|
|
389
|
-
*
|
390
|
-
|
391
|
-
This ensures that we call `PG::Connection.unescape_bytea` on PostgreSQL before decryption.
|
392
|
-
|
393
|
-
*Donal McBreen*
|
394
|
-
|
395
|
-
* Ensure `ActiveRecord::Encryption.config` is always ready before access.
|
396
|
-
|
397
|
-
Previously, `ActiveRecord::Encryption` configuration was deferred until `ActiveRecord::Base`
|
398
|
-
was loaded. Therefore, accessing `ActiveRecord::Encryption.config` properties before
|
399
|
-
`ActiveRecord::Base` was loaded would give incorrect results.
|
400
|
-
|
401
|
-
`ActiveRecord::Encryption` now has its own loading hook so that its configuration is set as
|
402
|
-
soon as needed.
|
403
|
-
|
404
|
-
When `ActiveRecord::Base` is loaded, even lazily, it in turn triggers the loading of
|
405
|
-
`ActiveRecord::Encryption`, thus preserving the original behavior of having its config ready
|
406
|
-
before any use of `ActiveRecord::Base`.
|
407
|
-
|
408
|
-
*Maxime Réty*
|
487
|
+
* Introduce a before-fork hook in `ActiveSupport::Testing::Parallelization` to clear existing
|
488
|
+
connections, to avoid fork-safety issues with the mysql2 adapter.
|
409
489
|
|
410
|
-
|
411
|
-
their type, scale, limit & precision.
|
490
|
+
Fixes #41776
|
412
491
|
|
413
|
-
|
492
|
+
*Mike Dalessio*, *Donal McBreen*
|
414
493
|
|
415
|
-
|
416
|
-
|
417
|
-
* Add support for SQLite3 full-text-search and other virtual tables.
|
418
|
-
|
419
|
-
Previously, adding sqlite3 virtual tables messed up `schema.rb`.
|
494
|
+
* PoolConfig no longer keeps a reference to the connection class.
|
420
495
|
|
421
|
-
|
496
|
+
Keeping a reference to the class caused subtle issues when combined with reloading in
|
497
|
+
development. Fixes #54343.
|
422
498
|
|
423
|
-
*
|
499
|
+
*Mike Dalessio*
|
424
500
|
|
425
|
-
*
|
501
|
+
* Fix SQL notifications sometimes not sent when using async queries.
|
426
502
|
|
427
503
|
```ruby
|
428
|
-
|
429
|
-
|
504
|
+
Post.async_count
|
505
|
+
ActiveSupport::Notifications.subscribed(->(*) { "Will never reach here" }) do
|
506
|
+
Post.count
|
430
507
|
end
|
431
508
|
```
|
432
509
|
|
433
|
-
|
510
|
+
In rare circumstances and under the right race condition, Active Support notifications
|
511
|
+
would no longer be dispatched after using an asynchronous query.
|
512
|
+
This is now fixed.
|
434
513
|
|
435
|
-
*
|
514
|
+
*Edouard Chin*
|
436
515
|
|
437
|
-
|
516
|
+
* Eliminate queries loading dumped schema cache on Postgres
|
438
517
|
|
439
|
-
|
518
|
+
Improve resiliency by avoiding needing to open a database connection to load the
|
519
|
+
type map while defining attribute methods at boot when a schema cache file is
|
520
|
+
configured on PostgreSQL databases.
|
440
521
|
|
441
|
-
|
442
|
-
with `:x` and `:y` keys of numeric values, mirroring the functionality of
|
443
|
-
existing casts for string and array values. Both string and symbol keys are
|
444
|
-
supported.
|
522
|
+
*James Coleman*
|
445
523
|
|
446
|
-
|
447
|
-
class PostgresqlPoint < ActiveRecord::Base
|
448
|
-
attribute :x, :point
|
449
|
-
attribute :y, :point
|
450
|
-
attribute :z, :point
|
451
|
-
end
|
524
|
+
* `ActiveRecord::Coder::JSON` can be instantiated
|
452
525
|
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
z: {x: '12.34', y: -43.21}
|
457
|
-
})
|
458
|
-
ActiveRecord::Point.new(12.32, -43.21) == val.x == val.y == val.z
|
526
|
+
Options can now be passed to `ActiveRecord::Coder::JSON` when instantiating the coder. This allows:
|
527
|
+
```ruby
|
528
|
+
serialize :config, coder: ActiveRecord::Coder::JSON.new(symbolize_names: true)
|
459
529
|
```
|
530
|
+
*matthaigh27*
|
460
531
|
|
461
|
-
|
532
|
+
* Deprecate using `insert_all`/`upsert_all` with unpersisted records in associations.
|
462
533
|
|
463
|
-
|
534
|
+
Using these methods on associations containing unpersisted records will now
|
535
|
+
show a deprecation warning, as the unpersisted records will be lost after
|
536
|
+
the operation.
|
464
537
|
|
465
|
-
|
538
|
+
*Nick Schwaderer*
|
466
539
|
|
467
|
-
|
540
|
+
* Make column name optional for `index_exists?`.
|
468
541
|
|
469
|
-
|
542
|
+
This aligns well with `remove_index` signature as well, where
|
543
|
+
index name doesn't need to be derived from the column names.
|
470
544
|
|
471
|
-
*
|
545
|
+
*Ali Ismayiliov*
|
472
546
|
|
473
|
-
*
|
547
|
+
* Change the payload name of `sql.active_record` notification for eager
|
548
|
+
loading from "SQL" to "#{model.name} Eager Load".
|
474
549
|
|
475
|
-
|
476
|
-
`enable_extension` statements if they differ from the current schema.
|
550
|
+
*zzak*
|
477
551
|
|
478
|
-
|
552
|
+
* Enable automatically retrying idempotent `#exists?` queries on connection
|
553
|
+
errors.
|
479
554
|
|
480
|
-
|
481
|
-
enable_extension "heroku_ext.pgcrypto"
|
482
|
-
enable_extension "pg_stat_statements"
|
483
|
-
```
|
555
|
+
*Hartley McGuire*, *classidied*
|
484
556
|
|
485
|
-
|
557
|
+
* Deprecate usage of unsupported methods in conjunction with `update_all`:
|
486
558
|
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
```
|
559
|
+
`update_all` will now print a deprecation message if a query includes either `WITH`,
|
560
|
+
`WITH RECURSIVE` or `DISTINCT` statements. Those were never supported and were ignored
|
561
|
+
when generating the SQL query.
|
491
562
|
|
492
|
-
|
563
|
+
An error will be raised in a future Rails release. This behavior will be consistent
|
564
|
+
with `delete_all` which currently raises an error for unsupported statements.
|
493
565
|
|
494
|
-
*
|
495
|
-
actual cast type.
|
566
|
+
*Edouard Chin*
|
496
567
|
|
497
|
-
|
568
|
+
* The table columns inside `schema.rb` are now sorted alphabetically.
|
498
569
|
|
499
|
-
|
570
|
+
Previously they'd be sorted by creation order, which can cause merge conflicts when two
|
571
|
+
branches modify the same table concurrently.
|
500
572
|
|
501
|
-
|
502
|
-
aggregated in a single bulk insert command.
|
573
|
+
*John Duff*
|
503
574
|
|
504
|
-
|
575
|
+
* Introduce versions formatter for the schema dumper.
|
505
576
|
|
506
|
-
|
577
|
+
It is now possible to override how schema dumper formats versions information inside the
|
578
|
+
`structure.sql` file. Currently, the versions are simply sorted in the decreasing order.
|
579
|
+
Within large teams, this can potentially cause many merge conflicts near the top of the list.
|
507
580
|
|
508
|
-
|
509
|
-
|
510
|
-
actually take a schema name (unlike `CREATE EXTENSION`), so the resulting SQL statement will only name
|
511
|
-
the extension, e.g. `DROP EXTENSION IF EXISTS "pgcrypto"`.
|
581
|
+
Now, the custom formatter can be provided with a custom sorting logic (e.g. by hash values
|
582
|
+
of the versions), which can greatly reduce the number of conflicts.
|
512
583
|
|
513
|
-
*
|
584
|
+
*fatkodima*
|
514
585
|
|
515
|
-
*
|
586
|
+
* Serialized attributes can now be marked as comparable.
|
516
587
|
|
517
|
-
|
588
|
+
A not rare issue when working with serialized attributes is that the serialized representation of an object
|
589
|
+
can change over time. Either because you are migrating from one serializer to the other (e.g. YAML to JSON or to msgpack),
|
590
|
+
or because the serializer used subtly changed its output.
|
518
591
|
|
519
|
-
|
592
|
+
One example is libyaml that used to have some extra trailing whitespaces, and recently fixed that.
|
593
|
+
When this sorts of thing happen, you end up with lots of records that report being changed even though
|
594
|
+
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.
|
520
595
|
|
521
|
-
|
596
|
+
The solution is to instead compare the deserialized representation of the object, however Active Record
|
597
|
+
can't assume the deserialized object has a working `==` method. Hence why this new functionality is opt-in.
|
522
598
|
|
523
599
|
```ruby
|
524
|
-
|
525
|
-
# do something with relation
|
526
|
-
end
|
600
|
+
serialize :config, type: Hash, coder: JSON, comparable: true
|
527
601
|
```
|
528
602
|
|
529
|
-
*
|
530
|
-
|
531
|
-
* Use SQLite `IMMEDIATE` transactions when possible.
|
532
|
-
|
533
|
-
Transactions run against the SQLite3 adapter default to IMMEDIATE mode to improve concurrency support and avoid busy exceptions.
|
534
|
-
|
535
|
-
*Stephen Margheim*
|
536
|
-
|
537
|
-
* Raise specific exception when a connection is not defined.
|
538
|
-
|
539
|
-
The new `ConnectionNotDefined` exception provides connection name, shard and role accessors indicating the details of the connection that was requested.
|
540
|
-
|
541
|
-
*Hana Harencarova*, *Matthew Draper*
|
603
|
+
*Jean Boussier*
|
542
604
|
|
543
|
-
*
|
605
|
+
* Fix MySQL default functions getting dropped when changing a column's nullability.
|
544
606
|
|
545
|
-
*
|
607
|
+
*Bastian Bartmann*
|
546
608
|
|
547
|
-
*
|
609
|
+
* SQLite extensions can be configured in `config/database.yml`.
|
548
610
|
|
549
|
-
|
550
|
-
|
611
|
+
The database configuration option `extensions:` allows an application to load SQLite extensions
|
612
|
+
when using `sqlite3` >= v2.4.0. The array members may be filesystem paths or the names of
|
613
|
+
modules that respond to `.to_path`:
|
551
614
|
|
552
|
-
|
615
|
+
``` yaml
|
616
|
+
development:
|
617
|
+
adapter: sqlite3
|
618
|
+
extensions:
|
619
|
+
- SQLean::UUID # module name responding to `.to_path`
|
620
|
+
- .sqlpkg/nalgeon/crypto/crypto.so # or a filesystem path
|
621
|
+
- <%= AppExtensions.location %> # or ruby code returning a path
|
622
|
+
```
|
553
623
|
|
554
|
-
*
|
624
|
+
*Mike Dalessio*
|
555
625
|
|
556
|
-
* `ActiveRecord::
|
626
|
+
* `ActiveRecord::Middleware::ShardSelector` supports granular database connection switching.
|
557
627
|
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
end
|
628
|
+
A new configuration option, `class_name:`, is introduced to
|
629
|
+
`config.active_record.shard_selector` to allow an application to specify the abstract connection
|
630
|
+
class to be switched by the shard selection middleware. The default class is
|
631
|
+
`ActiveRecord::Base`.
|
563
632
|
|
564
|
-
|
565
|
-
|
566
|
-
end
|
567
|
-
end
|
633
|
+
For example, this configuration tells `ShardSelector` to switch shards using
|
634
|
+
`AnimalsRecord.connected_to`:
|
568
635
|
|
569
|
-
class User
|
570
|
-
encrypts :name, compressor: ZstdCompressor
|
571
|
-
end
|
572
636
|
```
|
573
|
-
|
574
|
-
You disable compression by passing `compress: false`.
|
575
|
-
|
576
|
-
```ruby
|
577
|
-
class User
|
578
|
-
encrypts :name, compress: false
|
579
|
-
end
|
637
|
+
config.active_record.shard_selector = { class_name: "AnimalsRecord" }
|
580
638
|
```
|
581
639
|
|
582
|
-
*
|
583
|
-
|
584
|
-
* Add condensed `#inspect` for `ConnectionPool`, `AbstractAdapter`, and
|
585
|
-
`DatabaseConfig`.
|
586
|
-
|
587
|
-
*Hartley McGuire*
|
588
|
-
|
589
|
-
* Add `.shard_keys`, `.sharded?`, & `.connected_to_all_shards` methods.
|
590
|
-
|
591
|
-
```ruby
|
592
|
-
class ShardedBase < ActiveRecord::Base
|
593
|
-
self.abstract_class = true
|
594
|
-
|
595
|
-
connects_to shards: {
|
596
|
-
shard_one: { writing: :shard_one },
|
597
|
-
shard_two: { writing: :shard_two }
|
598
|
-
}
|
599
|
-
end
|
600
|
-
|
601
|
-
class ShardedModel < ShardedBase
|
602
|
-
end
|
640
|
+
*Mike Dalessio*
|
603
641
|
|
604
|
-
|
605
|
-
ShardedModel.sharded? => true
|
606
|
-
ShardedBase.connected_to_all_shards { ShardedModel.current_shard } => [:shard_one, :shard_two]
|
607
|
-
```
|
642
|
+
* Reset relations after `insert_all`/`upsert_all`.
|
608
643
|
|
609
|
-
|
644
|
+
Bulk insert/upsert methods will now call `reset` if used on a relation, matching the behavior of `update_all`.
|
610
645
|
|
611
|
-
*
|
612
|
-
by these values.
|
646
|
+
*Milo Winningham*
|
613
647
|
|
614
|
-
|
648
|
+
* Use `_N` as a parallel tests databases suffixes
|
615
649
|
|
616
|
-
|
617
|
-
|
650
|
+
Peviously, `-N` was used as a suffix. This can cause problems for RDBMSes
|
651
|
+
which do not support dashes in database names.
|
618
652
|
|
619
|
-
*
|
653
|
+
*fatkodima*
|
620
654
|
|
621
|
-
*
|
655
|
+
* Remember when a database connection has recently been verified (for
|
656
|
+
two seconds, by default), to avoid repeated reverifications during a
|
657
|
+
single request.
|
622
658
|
|
623
|
-
|
659
|
+
This should recreate a similar rate of verification as in Rails 7.1,
|
660
|
+
where connections are leased for the duration of a request, and thus
|
661
|
+
only verified once.
|
624
662
|
|
625
|
-
*
|
663
|
+
*Matthew Draper*
|
626
664
|
|
627
|
-
*
|
665
|
+
* Allow to reset cache counters for multiple records.
|
628
666
|
|
629
|
-
|
667
|
+
```
|
668
|
+
Aircraft.reset_counters([1, 2, 3], :wheels_count)
|
669
|
+
```
|
630
670
|
|
631
|
-
|
671
|
+
It produces much fewer queries compared to the custom implementation using looping over ids.
|
672
|
+
Previously: `O(ids.size * counters.size)` queries, now: `O(ids.size + counters.size)` queries.
|
632
673
|
|
633
|
-
*
|
634
|
-
structured (e.g., PostgreSQL +hstore+/+json+, or MySQL +json+) or declared serializable via
|
635
|
-
`ActiveRecord.store`.
|
674
|
+
*fatkodima*
|
636
675
|
|
637
|
-
|
676
|
+
* Add `affected_rows` to `sql.active_record` Notification.
|
638
677
|
|
639
|
-
|
678
|
+
*Hartley McGuire*
|
640
679
|
|
641
|
-
|
680
|
+
* Fix `sum` when performing a grouped calculation.
|
642
681
|
|
643
|
-
|
644
|
-
Please make sure the column is declared serializable via 'ActiveRecord.store' or, if your
|
645
|
-
database supports it, use a structured column type like hstore or json.
|
682
|
+
`User.group(:friendly).sum` no longer worked. This is fixed.
|
646
683
|
|
647
|
-
*
|
684
|
+
*Edouard Chin*
|
648
685
|
|
649
|
-
*
|
686
|
+
* Add support for enabling or disabling transactional tests per database.
|
650
687
|
|
651
|
-
|
688
|
+
A test class can now override the default `use_transactional_tests` setting
|
689
|
+
for individual databases, which can be useful if some databases need their
|
690
|
+
current state to be accessible to an external process while tests are running.
|
652
691
|
|
653
692
|
```ruby
|
654
|
-
class
|
655
|
-
|
693
|
+
class MostlyTransactionalTest < ActiveSupport::TestCase
|
694
|
+
self.use_transactional_tests = true
|
695
|
+
skip_transactional_tests_for_database :shared
|
656
696
|
end
|
657
697
|
```
|
658
698
|
|
659
|
-
|
699
|
+
*Matthew Cheetham*, *Morgan Mareve*
|
660
700
|
|
661
|
-
|
701
|
+
* Cast `query_cache` value when using URL configuration.
|
702
|
+
|
703
|
+
*zzak*
|
662
704
|
|
663
|
-
*
|
705
|
+
* NULLS NOT DISTINCT works with UNIQUE CONSTRAINT as well as UNIQUE INDEX.
|
664
706
|
|
665
|
-
|
707
|
+
*Ryuta Kamizono*
|
666
708
|
|
667
|
-
|
668
|
-
ActiveRecord.schema_cache_ignored_tables = ["developers"]
|
669
|
-
ActiveRecord.schema_cache_ignored_table?("developers")
|
670
|
-
=> true
|
671
|
-
```
|
709
|
+
* `PG::UnableToSend: no connection to the server` is now retryable as a connection-related exception
|
672
710
|
|
673
|
-
*
|
711
|
+
*Kazuma Watanabe*
|
674
712
|
|
675
|
-
Please check [
|
713
|
+
Please check [8-0-stable](https://github.com/rails/rails/blob/8-0-stable/activerecord/CHANGELOG.md) for previous changes.
|