activerecord 7.1.3.4 → 7.2.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +514 -2126
- data/README.rdoc +15 -15
- data/examples/performance.rb +2 -2
- data/lib/active_record/association_relation.rb +1 -1
- data/lib/active_record/associations/alias_tracker.rb +25 -19
- data/lib/active_record/associations/association.rb +9 -8
- data/lib/active_record/associations/belongs_to_association.rb +18 -11
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -2
- data/lib/active_record/associations/builder/belongs_to.rb +1 -0
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +2 -2
- data/lib/active_record/associations/builder/has_many.rb +3 -4
- data/lib/active_record/associations/builder/has_one.rb +3 -4
- data/lib/active_record/associations/collection_association.rb +4 -2
- data/lib/active_record/associations/collection_proxy.rb +14 -1
- data/lib/active_record/associations/has_many_association.rb +3 -3
- data/lib/active_record/associations/has_one_association.rb +2 -2
- data/lib/active_record/associations/join_dependency/join_association.rb +27 -25
- data/lib/active_record/associations/join_dependency.rb +5 -7
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +2 -1
- data/lib/active_record/associations/preloader/branch.rb +7 -1
- data/lib/active_record/associations/preloader/through_association.rb +1 -3
- data/lib/active_record/associations/singular_association.rb +6 -0
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +34 -11
- data/lib/active_record/attribute_assignment.rb +1 -11
- data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
- data/lib/active_record/attribute_methods/dirty.rb +1 -1
- data/lib/active_record/attribute_methods/primary_key.rb +23 -55
- data/lib/active_record/attribute_methods/read.rb +1 -13
- data/lib/active_record/attribute_methods/serialization.rb +4 -24
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +7 -6
- data/lib/active_record/attribute_methods.rb +87 -58
- data/lib/active_record/attributes.rb +55 -42
- data/lib/active_record/autosave_association.rb +14 -30
- data/lib/active_record/base.rb +2 -3
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +24 -107
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +1 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +248 -58
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +35 -18
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +161 -75
- data/lib/active_record/connection_adapters/abstract/quoting.rb +65 -91
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +22 -9
- data/lib/active_record/connection_adapters/abstract/transaction.rb +65 -60
- data/lib/active_record/connection_adapters/abstract_adapter.rb +33 -61
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +69 -19
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +9 -1
- data/lib/active_record/connection_adapters/mysql/quoting.rb +43 -48
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +7 -0
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +11 -5
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +20 -32
- data/lib/active_record/connection_adapters/pool_config.rb +7 -6
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +27 -4
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +58 -58
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +20 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +16 -12
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +26 -21
- data/lib/active_record/connection_adapters/schema_cache.rb +123 -128
- data/lib/active_record/connection_adapters/sqlite3/column.rb +14 -1
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +10 -6
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +44 -46
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +13 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +25 -2
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +109 -77
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +12 -6
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +32 -65
- data/lib/active_record/connection_adapters.rb +121 -0
- data/lib/active_record/connection_handling.rb +56 -41
- data/lib/active_record/core.rb +59 -38
- data/lib/active_record/counter_cache.rb +23 -10
- data/lib/active_record/database_configurations/connection_url_resolver.rb +7 -2
- data/lib/active_record/database_configurations/database_config.rb +15 -4
- data/lib/active_record/database_configurations/hash_config.rb +44 -36
- data/lib/active_record/database_configurations/url_config.rb +20 -1
- data/lib/active_record/database_configurations.rb +1 -1
- data/lib/active_record/delegated_type.rb +30 -6
- data/lib/active_record/destroy_association_async_job.rb +1 -1
- data/lib/active_record/dynamic_matchers.rb +2 -2
- data/lib/active_record/encryption/encryptable_record.rb +2 -2
- data/lib/active_record/encryption/encrypted_attribute_type.rb +24 -4
- data/lib/active_record/encryption/encryptor.rb +17 -2
- data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
- data/lib/active_record/encryption/message_serializer.rb +4 -0
- data/lib/active_record/encryption/null_encryptor.rb +4 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +4 -0
- data/lib/active_record/encryption/scheme.rb +8 -4
- data/lib/active_record/enum.rb +11 -2
- data/lib/active_record/errors.rb +16 -11
- data/lib/active_record/explain.rb +13 -24
- data/lib/active_record/fixtures.rb +37 -31
- data/lib/active_record/future_result.rb +17 -4
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +4 -2
- data/lib/active_record/insert_all.rb +18 -15
- data/lib/active_record/integration.rb +4 -1
- data/lib/active_record/internal_metadata.rb +48 -34
- data/lib/active_record/locking/optimistic.rb +8 -7
- data/lib/active_record/log_subscriber.rb +0 -21
- data/lib/active_record/marshalling.rb +1 -1
- data/lib/active_record/message_pack.rb +2 -2
- data/lib/active_record/migration/command_recorder.rb +2 -3
- data/lib/active_record/migration/compatibility.rb +11 -3
- data/lib/active_record/migration/default_strategy.rb +4 -5
- data/lib/active_record/migration/pending_migration_connection.rb +2 -2
- data/lib/active_record/migration.rb +85 -76
- data/lib/active_record/model_schema.rb +34 -69
- data/lib/active_record/nested_attributes.rb +11 -3
- data/lib/active_record/normalization.rb +3 -7
- data/lib/active_record/persistence.rb +32 -354
- data/lib/active_record/query_cache.rb +18 -6
- data/lib/active_record/query_logs.rb +15 -0
- data/lib/active_record/query_logs_formatter.rb +1 -1
- data/lib/active_record/querying.rb +21 -9
- data/lib/active_record/railtie.rb +52 -64
- data/lib/active_record/railties/controller_runtime.rb +13 -4
- data/lib/active_record/railties/databases.rake +41 -44
- data/lib/active_record/reflection.rb +98 -37
- data/lib/active_record/relation/batches/batch_enumerator.rb +15 -2
- data/lib/active_record/relation/batches.rb +3 -3
- data/lib/active_record/relation/calculations.rb +94 -61
- data/lib/active_record/relation/delegation.rb +8 -11
- data/lib/active_record/relation/finder_methods.rb +16 -2
- data/lib/active_record/relation/merger.rb +4 -6
- data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +6 -1
- data/lib/active_record/relation/predicate_builder.rb +3 -3
- data/lib/active_record/relation/query_methods.rb +197 -44
- data/lib/active_record/relation/record_fetch_warning.rb +3 -0
- data/lib/active_record/relation/spawn_methods.rb +2 -18
- data/lib/active_record/relation/where_clause.rb +7 -19
- data/lib/active_record/relation.rb +500 -66
- data/lib/active_record/result.rb +32 -45
- data/lib/active_record/runtime_registry.rb +39 -0
- data/lib/active_record/sanitization.rb +24 -19
- data/lib/active_record/schema.rb +8 -6
- data/lib/active_record/schema_dumper.rb +19 -9
- data/lib/active_record/schema_migration.rb +30 -14
- data/lib/active_record/signed_id.rb +11 -1
- data/lib/active_record/statement_cache.rb +7 -7
- data/lib/active_record/table_metadata.rb +1 -10
- data/lib/active_record/tasks/database_tasks.rb +70 -42
- data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/postgresql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -1
- data/lib/active_record/test_fixtures.rb +82 -91
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +4 -2
- data/lib/active_record/token_for.rb +22 -12
- data/lib/active_record/touch_later.rb +1 -1
- data/lib/active_record/transaction.rb +131 -0
- data/lib/active_record/transactions.rb +70 -14
- data/lib/active_record/translation.rb +0 -2
- data/lib/active_record/type/serialized.rb +1 -3
- data/lib/active_record/type_caster/connection.rb +4 -4
- data/lib/active_record/validations/associated.rb +9 -3
- data/lib/active_record/validations/uniqueness.rb +14 -10
- data/lib/active_record/validations.rb +4 -1
- data/lib/active_record.rb +149 -40
- data/lib/arel/alias_predication.rb +1 -1
- data/lib/arel/collectors/bind.rb +2 -0
- data/lib/arel/collectors/composite.rb +7 -0
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +1 -1
- data/lib/arel/nodes/binary.rb +0 -6
- data/lib/arel/nodes/bound_sql_literal.rb +9 -5
- data/lib/arel/nodes/{and.rb → nary.rb} +5 -2
- data/lib/arel/nodes/node.rb +4 -3
- data/lib/arel/nodes/sql_literal.rb +7 -0
- data/lib/arel/nodes.rb +2 -2
- data/lib/arel/predications.rb +1 -1
- data/lib/arel/select_manager.rb +1 -1
- data/lib/arel/tree_manager.rb +8 -3
- data/lib/arel/update_manager.rb +2 -1
- data/lib/arel/visitors/dot.rb +1 -0
- data/lib/arel/visitors/mysql.rb +9 -4
- data/lib/arel/visitors/postgresql.rb +1 -12
- data/lib/arel/visitors/to_sql.rb +31 -17
- data/lib/arel.rb +7 -3
- metadata +17 -12
data/CHANGELOG.md
CHANGED
@@ -1,2478 +1,866 @@
|
|
1
|
-
## Rails 7.
|
1
|
+
## Rails 7.2.0.beta2 (June 04, 2024) ##
|
2
2
|
|
3
|
-
*
|
3
|
+
* The payload of `sql.active_record` Active Support notifications now has the current transaction in the `:transaction` key.
|
4
4
|
|
5
|
+
*Xavier Noria*
|
5
6
|
|
6
|
-
|
7
|
+
* The payload of `transaction.active_record` Active Support notifications now has the transaction the event is related to in the `:transaction` key.
|
7
8
|
|
8
|
-
*
|
9
|
+
*Xavier Noria*
|
9
10
|
|
11
|
+
* Define `ActiveRecord::Transaction#uuid`, which returns a UUID for the database transaction. This may be helpful when tracing database activity. These UUIDs are generated only on demand.
|
10
12
|
|
11
|
-
|
13
|
+
*Xavier Noria*
|
12
14
|
|
13
|
-
|
15
|
+
## Rails 7.2.0.beta1 (May 29, 2024) ##
|
14
16
|
|
17
|
+
* Fix inference of association model on nested models with the same demodularized name.
|
15
18
|
|
16
|
-
|
17
|
-
|
18
|
-
* No changes.
|
19
|
-
|
20
|
-
|
21
|
-
## Rails 7.1.3 (January 16, 2024) ##
|
22
|
-
|
23
|
-
* Fix Migrations with versions older than 7.1 validating options given to
|
24
|
-
`add_reference`.
|
25
|
-
|
26
|
-
*Hartley McGuire*
|
27
|
-
|
28
|
-
* Ensure `reload` sets correct owner for each association.
|
29
|
-
|
30
|
-
*Dmytro Savochkin*
|
31
|
-
|
32
|
-
* Fix view runtime for controllers with async queries.
|
33
|
-
|
34
|
-
*fatkodima*
|
35
|
-
|
36
|
-
* Fix `load_async` to work with query cache.
|
37
|
-
|
38
|
-
*fatkodima*
|
39
|
-
|
40
|
-
* Fix polymorphic `belongs_to` to correctly use parent's `query_constraints`.
|
41
|
-
|
42
|
-
*fatkodima*
|
43
|
-
|
44
|
-
* Fix `Preloader` to not generate a query for already loaded association with `query_constraints`.
|
45
|
-
|
46
|
-
*fatkodima*
|
47
|
-
|
48
|
-
* Fix multi-database polymorphic preloading with equivalent table names.
|
49
|
-
|
50
|
-
When preloading polymorphic associations, if two models pointed to two
|
51
|
-
tables with the same name but located in different databases, the
|
52
|
-
preloader would only load one.
|
53
|
-
|
54
|
-
*Ari Summer*
|
55
|
-
|
56
|
-
* Fix `encrypted_attribute?` to take into account context properties passed to `encrypts`.
|
57
|
-
|
58
|
-
*Maxime Réty*
|
59
|
-
|
60
|
-
* Fix `find_by` to work correctly in presence of composite primary keys.
|
61
|
-
|
62
|
-
*fatkodima*
|
63
|
-
|
64
|
-
* Fix async queries sometimes returning a raw result if they hit the query cache.
|
65
|
-
|
66
|
-
`ShipPart.async_count` could return a raw integer rather than a Promise
|
67
|
-
if it found the result in the query cache.
|
68
|
-
|
69
|
-
*fatkodima*
|
70
|
-
|
71
|
-
* Fix `Relation#transaction` to not apply a default scope.
|
72
|
-
|
73
|
-
The method was incorrectly setting a default scope around its block:
|
74
|
-
|
75
|
-
```ruby
|
76
|
-
Post.where(published: true).transaction do
|
77
|
-
Post.count # SELECT COUNT(*) FROM posts WHERE published = FALSE;
|
78
|
-
end
|
79
|
-
```
|
80
|
-
|
81
|
-
*Jean Boussier*
|
82
|
-
|
83
|
-
* Fix calling `async_pluck` on a `none` relation.
|
84
|
-
|
85
|
-
`Model.none.async_pluck(:id)` was returning a naked value
|
86
|
-
instead of a promise.
|
87
|
-
|
88
|
-
*Jean Boussier*
|
89
|
-
|
90
|
-
* Fix calling `load_async` on a `none` relation.
|
91
|
-
|
92
|
-
`Model.none.load_async` was returning a broken result.
|
93
|
-
|
94
|
-
*Lucas Mazza*
|
95
|
-
|
96
|
-
* TrilogyAdapter: ignore `host` if `socket` parameter is set.
|
97
|
-
|
98
|
-
This allows to configure a connection on a UNIX socket via DATABASE_URL:
|
99
|
-
|
100
|
-
```
|
101
|
-
DATABASE_URL=trilogy://does-not-matter/my_db_production?socket=/var/run/mysql.sock
|
102
|
-
```
|
103
|
-
|
104
|
-
*Jean Boussier*
|
105
|
-
|
106
|
-
* Fix `has_secure_token` calls the setter method on initialize.
|
107
|
-
|
108
|
-
*Abeid Ahmed*
|
109
|
-
|
110
|
-
* Allow using `object_id` as a database column name.
|
111
|
-
It was available before rails 7.1 and may be used as a part of polymorphic relationship to `object` where `object` can be any other database record.
|
112
|
-
|
113
|
-
*Mikhail Doronin*
|
114
|
-
|
115
|
-
* Fix `rails db:create:all` to not touch databases before they are created.
|
116
|
-
|
117
|
-
*fatkodima*
|
118
|
-
|
119
|
-
|
120
|
-
## Rails 7.1.2 (November 10, 2023) ##
|
121
|
-
|
122
|
-
* Fix renaming primary key index when renaming a table with a UUID primary key
|
123
|
-
in PostgreSQL.
|
124
|
-
|
125
|
-
*fatkodima*
|
126
|
-
|
127
|
-
* Fix `where(field: values)` queries when `field` is a serialized attribute
|
128
|
-
(for example, when `field` uses `ActiveRecord::Base.serialize` or is a JSON
|
129
|
-
column).
|
130
|
-
|
131
|
-
*João Alves*
|
132
|
-
|
133
|
-
* Prevent marking broken connections as verified.
|
134
|
-
|
135
|
-
*Daniel Colson*
|
136
|
-
|
137
|
-
* Don't mark Float::INFINITY as changed when reassigning it
|
138
|
-
|
139
|
-
When saving a record with a float infinite value, it shouldn't mark as changed
|
140
|
-
|
141
|
-
*Maicol Bentancor*
|
142
|
-
|
143
|
-
* `ActiveRecord::Base.table_name` now returns `nil` instead of raising
|
144
|
-
"undefined method `abstract_class?` for Object:Class".
|
145
|
-
|
146
|
-
*a5-stable*
|
147
|
-
|
148
|
-
* Fix upserting for custom `:on_duplicate` and `:unique_by` consisting of all
|
149
|
-
inserts keys.
|
150
|
-
|
151
|
-
*fatkodima*
|
152
|
-
|
153
|
-
* Fixed an [issue](https://github.com/rails/rails/issues/49809) where saving a
|
154
|
-
record could innappropriately `dup` its attributes.
|
155
|
-
|
156
|
-
*Jonathan Hefner*
|
157
|
-
|
158
|
-
* Dump schema only for a specific db for rollback/up/down tasks for multiple dbs.
|
159
|
-
|
160
|
-
*fatkodima*
|
161
|
-
|
162
|
-
* Fix `NoMethodError` when casting a PostgreSQL `money` value that uses a
|
163
|
-
comma as its radix point and has no leading currency symbol. For example,
|
164
|
-
when casting `"3,50"`.
|
165
|
-
|
166
|
-
*Andreas Reischuck* and *Jonathan Hefner*
|
167
|
-
|
168
|
-
* Re-enable support for using `enum` with non-column-backed attributes.
|
169
|
-
Non-column-backed attributes must be previously declared with an explicit
|
170
|
-
type. For example:
|
171
|
-
|
172
|
-
```ruby
|
173
|
-
class Post < ActiveRecord::Base
|
174
|
-
attribute :topic, :string
|
175
|
-
enum topic: %i[science tech engineering math]
|
176
|
-
end
|
177
|
-
```
|
178
|
-
|
179
|
-
*Jonathan Hefner*
|
180
|
-
|
181
|
-
* Raise on `foreign_key:` being passed as an array in associations
|
182
|
-
|
183
|
-
*Nikita Vasilevsky*
|
184
|
-
|
185
|
-
* Return back maximum allowed PostgreSQL table name to 63 characters.
|
186
|
-
|
187
|
-
*fatkodima*
|
188
|
-
|
189
|
-
* Fix detecting `IDENTITY` columns for PostgreSQL < 10.
|
190
|
-
|
191
|
-
*fatkodima*
|
192
|
-
|
193
|
-
|
194
|
-
## Rails 7.1.1 (October 11, 2023) ##
|
195
|
-
|
196
|
-
* Fix auto populating IDENTITY columns for PostgreSQL.
|
197
|
-
|
198
|
-
*fatkodima*
|
199
|
-
|
200
|
-
* Fix "ArgumentError: wrong number of arguments (given 3, expected 2)" when
|
201
|
-
down migrating `rename_table` in older migrations.
|
202
|
-
|
203
|
-
*fatkodima*
|
204
|
-
|
205
|
-
* Do not require the Action Text, Active Storage and Action Mailbox tables
|
206
|
-
to be present when running when running test on CI.
|
207
|
-
|
208
|
-
*Rafael Mendonça França*
|
209
|
-
|
210
|
-
|
211
|
-
## Rails 7.1.0 (October 05, 2023) ##
|
212
|
-
|
213
|
-
* No changes.
|
214
|
-
|
215
|
-
|
216
|
-
## Rails 7.1.0.rc2 (October 01, 2023) ##
|
217
|
-
|
218
|
-
* Remove -shm and -wal SQLite files when `rails db:drop` is run.
|
219
|
-
|
220
|
-
*Niklas Häusele*
|
221
|
-
|
222
|
-
* Revert the change to raise an `ArgumentError` when `#accepts_nested_attributes_for` is declared more than once for
|
223
|
-
an association in the same class.
|
224
|
-
|
225
|
-
The reverted behavior broke the case where the `#accepts_nested_attributes_for` was defined in a concern and
|
226
|
-
where overridden in the class that included the concern.
|
227
|
-
|
228
|
-
*Rafael Mendonça França*
|
229
|
-
|
230
|
-
|
231
|
-
## Rails 7.1.0.rc1 (September 27, 2023) ##
|
232
|
-
|
233
|
-
* Better naming for unique constraints support.
|
234
|
-
|
235
|
-
Naming unique keys leads to misunderstanding it's a short-hand of unique indexes.
|
236
|
-
Just naming it unique constraints is not misleading.
|
237
|
-
|
238
|
-
In Rails 7.1.0.beta1 or before:
|
239
|
-
|
240
|
-
```ruby
|
241
|
-
add_unique_key :sections, [:position], deferrable: :deferred, name: "unique_section_position"
|
242
|
-
remove_unique_key :sections, name: "unique_section_position"
|
243
|
-
```
|
244
|
-
|
245
|
-
Now:
|
246
|
-
|
247
|
-
```ruby
|
248
|
-
add_unique_constraint :sections, [:position], deferrable: :deferred, name: "unique_section_position"
|
249
|
-
remove_unique_constraint :sections, name: "unique_section_position"
|
250
|
-
```
|
251
|
-
|
252
|
-
*Ryuta Kamizono*
|
253
|
-
|
254
|
-
* Fix duplicate quoting for check constraint expressions in schema dump when using MySQL
|
255
|
-
|
256
|
-
A check constraint with an expression, that already contains quotes, lead to an invalid schema
|
257
|
-
dump with the mysql2 adapter.
|
258
|
-
|
259
|
-
Fixes #42424.
|
260
|
-
|
261
|
-
*Felix Tscheulin*
|
262
|
-
|
263
|
-
* Performance tune the SQLite3 adapter connection configuration
|
264
|
-
|
265
|
-
For Rails applications, the Write-Ahead-Log in normal syncing mode with a capped journal size, a healthy shared memory buffer and a shared cache will perform, on average, 2× better.
|
266
|
-
|
267
|
-
*Stephen Margheim*
|
268
|
-
|
269
|
-
* Allow SQLite3 `busy_handler` to be configured with simple max number of `retries`
|
270
|
-
|
271
|
-
Retrying busy connections without delay is a preferred practice for performance-sensitive applications. Add support for a `database.yml` `retries` integer, which is used in a simple `busy_handler` function to retry busy connections without exponential backoff up to the max number of `retries`.
|
272
|
-
|
273
|
-
*Stephen Margheim*
|
274
|
-
|
275
|
-
* The SQLite3 adapter now supports `supports_insert_returning?`
|
276
|
-
|
277
|
-
Implementing the full `supports_insert_returning?` contract means the SQLite3 adapter supports auto-populated columns (#48241) as well as custom primary keys.
|
278
|
-
|
279
|
-
*Stephen Margheim*
|
280
|
-
|
281
|
-
* Ensure the SQLite3 adapter handles default functions with the `||` concatenation operator
|
282
|
-
|
283
|
-
Previously, this default function would produce the static string `"'Ruby ' || 'on ' || 'Rails'"`.
|
284
|
-
Now, the adapter will appropriately receive and use `"Ruby on Rails"`.
|
285
|
-
|
286
|
-
```ruby
|
287
|
-
change_column_default "test_models", "ruby_on_rails", -> { "('Ruby ' || 'on ' || 'Rails')" }
|
288
|
-
```
|
289
|
-
|
290
|
-
*Stephen Margheim*
|
291
|
-
|
292
|
-
* Dump PostgreSQL schemas as part of the schema dump.
|
293
|
-
|
294
|
-
*Lachlan Sylvester*
|
295
|
-
|
296
|
-
|
297
|
-
## Rails 7.1.0.beta1 (September 13, 2023) ##
|
298
|
-
|
299
|
-
* Encryption now supports `support_unencrypted_data` being set per-attribute.
|
300
|
-
|
301
|
-
You can now opt out of `support_unencrypted_data` on a specific encrypted attribute.
|
302
|
-
This only has an effect if `ActiveRecord::Encryption.config.support_unencrypted_data == true`.
|
303
|
-
|
304
|
-
```ruby
|
305
|
-
class User < ActiveRecord::Base
|
306
|
-
encrypts :name, deterministic: true, support_unencrypted_data: false
|
307
|
-
encrypts :email, deterministic: true
|
308
|
-
end
|
309
|
-
```
|
310
|
-
|
311
|
-
*Alex Ghiculescu*
|
312
|
-
|
313
|
-
* Add instrumentation for Active Record transactions
|
314
|
-
|
315
|
-
Allows subscribing to transaction events for tracking/instrumentation. The event payload contains the connection and the outcome (commit, rollback, restart, incomplete), as well as timing details.
|
316
|
-
|
317
|
-
```ruby
|
318
|
-
ActiveSupport::Notifications.subscribe("transaction.active_record") do |event|
|
319
|
-
puts "Transaction event occurred!"
|
320
|
-
connection = event.payload[:connection]
|
321
|
-
puts "Connection: #{connection.inspect}"
|
322
|
-
end
|
323
|
-
```
|
324
|
-
|
325
|
-
*Daniel Colson*, *Ian Candy*
|
326
|
-
|
327
|
-
* Support composite foreign keys via migration helpers.
|
328
|
-
|
329
|
-
```ruby
|
330
|
-
# Assuming "carts" table has "(shop_id, user_id)" as a primary key.
|
331
|
-
|
332
|
-
add_foreign_key(:orders, :carts, primary_key: [:shop_id, :user_id])
|
333
|
-
|
334
|
-
remove_foreign_key(:orders, :carts, primary_key: [:shop_id, :user_id])
|
335
|
-
foreign_key_exists?(:orders, :carts, primary_key: [:shop_id, :user_id])
|
336
|
-
```
|
337
|
-
|
338
|
-
*fatkodima*
|
339
|
-
|
340
|
-
* Adds support for `if_not_exists` when adding a check constraint.
|
341
|
-
|
342
|
-
```ruby
|
343
|
-
add_check_constraint :posts, "post_type IN ('blog', 'comment', 'share')", if_not_exists: true
|
344
|
-
```
|
345
|
-
|
346
|
-
*Cody Cutrer*
|
347
|
-
|
348
|
-
* Raise an `ArgumentError` when `#accepts_nested_attributes_for` is declared more than once for an association in
|
349
|
-
the same class. Previously, the last declaration would silently override the previous one. Overriding in a subclass
|
350
|
-
is still allowed.
|
351
|
-
|
352
|
-
*Joshua Young*
|
353
|
-
|
354
|
-
* Deprecate `rewhere` argument on `#merge`.
|
355
|
-
|
356
|
-
The `rewhere` argument on `#merge`is deprecated without replacement and
|
357
|
-
will be removed in Rails 7.2.
|
358
|
-
|
359
|
-
*Adam Hess*
|
360
|
-
|
361
|
-
* Deprecate aliasing non-attributes with `alias_attribute`.
|
362
|
-
|
363
|
-
*Ian Candy*
|
364
|
-
|
365
|
-
* Fix unscope is not working in specific case
|
366
|
-
|
367
|
-
Before:
|
368
|
-
```ruby
|
369
|
-
Post.where(id: 1...3).unscope(where: :id).to_sql # "SELECT `posts`.* FROM `posts` WHERE `posts`.`id` >= 1 AND `posts`.`id` < 3"
|
370
|
-
|
371
|
-
```
|
372
|
-
|
373
|
-
After:
|
374
|
-
```ruby
|
375
|
-
Post.where(id: 1...3).unscope(where: :id).to_sql # "SELECT `posts`.* FROM `posts`"
|
376
|
-
```
|
377
|
-
|
378
|
-
Fixes #48094.
|
379
|
-
|
380
|
-
*Kazuya Hatanaka*
|
381
|
-
|
382
|
-
* Change `has_secure_token` default to `on: :initialize`
|
383
|
-
|
384
|
-
Change the new default value from `on: :create` to `on: :initialize`
|
385
|
-
|
386
|
-
Can be controlled by the `config.active_record.generate_secure_token_on`
|
387
|
-
configuration:
|
388
|
-
|
389
|
-
```ruby
|
390
|
-
config.active_record.generate_secure_token_on = :create
|
391
|
-
```
|
392
|
-
|
393
|
-
*Sean Doyle*
|
394
|
-
|
395
|
-
* Fix `change_column` not setting `precision: 6` on `datetime` columns when
|
396
|
-
using 7.0+ Migrations and SQLite.
|
397
|
-
|
398
|
-
*Hartley McGuire*
|
399
|
-
|
400
|
-
* Support composite identifiers in `to_key`
|
401
|
-
|
402
|
-
`to_key` avoids wrapping `#id` value into an `Array` if `#id` already an array
|
403
|
-
|
404
|
-
*Nikita Vasilevsky*
|
405
|
-
|
406
|
-
* Add validation option for `enum`
|
407
|
-
|
408
|
-
```ruby
|
409
|
-
class Contract < ApplicationRecord
|
410
|
-
enum :status, %w[in_progress completed], validate: true
|
411
|
-
end
|
412
|
-
Contract.new(status: "unknown").valid? # => false
|
413
|
-
Contract.new(status: nil).valid? # => false
|
414
|
-
Contract.new(status: "completed").valid? # => true
|
415
|
-
|
416
|
-
class Contract < ApplicationRecord
|
417
|
-
enum :status, %w[in_progress completed], validate: { allow_nil: true }
|
418
|
-
end
|
419
|
-
Contract.new(status: "unknown").valid? # => false
|
420
|
-
Contract.new(status: nil).valid? # => true
|
421
|
-
Contract.new(status: "completed").valid? # => true
|
422
|
-
```
|
423
|
-
|
424
|
-
*Edem Topuzov*, *Ryuta Kamizono*
|
425
|
-
|
426
|
-
* Allow batching methods to use already loaded relation if available
|
427
|
-
|
428
|
-
Calling batch methods on already loaded relations will use the records previously loaded instead of retrieving
|
429
|
-
them from the database again.
|
430
|
-
|
431
|
-
*Adam Hess*
|
432
|
-
|
433
|
-
* Deprecate `read_attribute(:id)` returning the primary key if the primary key is not `:id`.
|
434
|
-
|
435
|
-
Starting in Rails 7.2, `read_attribute(:id)` will return the value of the id column, regardless of the model's
|
436
|
-
primary key. To retrieve the value of the primary key, use `#id` instead. `read_attribute(:id)` for composite
|
437
|
-
primary key models will now return the value of the id column.
|
438
|
-
|
439
|
-
*Adrianna Chang*
|
440
|
-
|
441
|
-
* Fix `change_table` setting datetime precision for 6.1 Migrations
|
442
|
-
|
443
|
-
*Hartley McGuire*
|
444
|
-
|
445
|
-
* Fix change_column setting datetime precision for 6.1 Migrations
|
446
|
-
|
447
|
-
*Hartley McGuire*
|
448
|
-
|
449
|
-
* Add `ActiveRecord::Base#id_value` alias to access the raw value of a record's id column.
|
450
|
-
|
451
|
-
This alias is only provided for models that declare an `:id` column.
|
452
|
-
|
453
|
-
*Adrianna Chang*
|
454
|
-
|
455
|
-
* Fix previous change tracking for `ActiveRecord::Store` when using a column with JSON structured database type
|
456
|
-
|
457
|
-
Before, the methods to access the changes made during the last save `#saved_change_to_key?`, `#saved_change_to_key`, and `#key_before_last_save` did not work if the store was defined as a `store_accessor` on a column with a JSON structured database type
|
458
|
-
|
459
|
-
*Robert DiMartino*
|
460
|
-
|
461
|
-
* Fully support `NULLS [NOT] DISTINCT` for PostgreSQL 15+ indexes.
|
462
|
-
|
463
|
-
Previous work was done to allow the index to be created in a migration, but it was not
|
464
|
-
supported in schema.rb. Additionally, the matching for `NULLS [NOT] DISTINCT` was not
|
465
|
-
in the correct order, which could have resulted in inconsistent schema detection.
|
466
|
-
|
467
|
-
*Gregory Jones*
|
468
|
-
|
469
|
-
* Allow escaping of literal colon characters in `sanitize_sql_*` methods when named bind variables are used
|
470
|
-
|
471
|
-
*Justin Bull*
|
472
|
-
|
473
|
-
* Fix `#previously_new_record?` to return true for destroyed records.
|
474
|
-
|
475
|
-
Before, if a record was created and then destroyed, `#previously_new_record?` would return true.
|
476
|
-
Now, any UPDATE or DELETE to a record is considered a change, and will result in `#previously_new_record?`
|
477
|
-
returning false.
|
478
|
-
|
479
|
-
*Adrianna Chang*
|
480
|
-
|
481
|
-
* Specify callback in `has_secure_token`
|
482
|
-
|
483
|
-
```ruby
|
484
|
-
class User < ApplicationRecord
|
485
|
-
has_secure_token on: :initialize
|
486
|
-
end
|
487
|
-
|
488
|
-
User.new.token # => "abc123...."
|
489
|
-
```
|
490
|
-
|
491
|
-
*Sean Doyle*
|
492
|
-
|
493
|
-
* Fix incrementation of in memory counter caches when associations overlap
|
494
|
-
|
495
|
-
When two associations had a similarly named counter cache column, Active Record
|
496
|
-
could sometime increment the wrong one.
|
497
|
-
|
498
|
-
*Jacopo Beschi*, *Jean Boussier*
|
499
|
-
|
500
|
-
* Don't show secrets for Active Record's `Cipher::Aes256Gcm#inspect`.
|
501
|
-
|
502
|
-
Before:
|
503
|
-
|
504
|
-
```ruby
|
505
|
-
ActiveRecord::Encryption::Cipher::Aes256Gcm.new(secret).inspect
|
506
|
-
"#<ActiveRecord::Encryption::Cipher::Aes256Gcm:0x0000000104888038 ... @secret=\"\\xAF\\bFh]LV}q\\nl\\xB2U\\xB3 ... >"
|
507
|
-
```
|
508
|
-
|
509
|
-
After:
|
510
|
-
|
511
|
-
```ruby
|
512
|
-
ActiveRecord::Encryption::Cipher::Aes256Gcm(secret).inspect
|
513
|
-
"#<ActiveRecord::Encryption::Cipher::Aes256Gcm:0x0000000104888038>"
|
514
|
-
```
|
515
|
-
|
516
|
-
*Petrik de Heus*
|
517
|
-
|
518
|
-
* Bring back the historical behavior of committing transaction on non-local return.
|
519
|
-
|
520
|
-
```ruby
|
521
|
-
Model.transaction do
|
522
|
-
model.save
|
523
|
-
return
|
524
|
-
other_model.save # not executed
|
525
|
-
end
|
526
|
-
```
|
527
|
-
|
528
|
-
Historically only raised errors would trigger a rollback, but in Ruby `2.3`, the `timeout` library
|
529
|
-
started using `throw` to interrupt execution which had the adverse effect of committing open transactions.
|
530
|
-
|
531
|
-
To solve this, in Active Record 6.1 the behavior was changed to instead rollback the transaction as it was safer
|
532
|
-
than to potentially commit an incomplete transaction.
|
533
|
-
|
534
|
-
Using `return`, `break` or `throw` inside a `transaction` block was essentially deprecated from Rails 6.1 onwards.
|
535
|
-
|
536
|
-
However with the release of `timeout 0.4.0`, `Timeout.timeout` now raises an error again, and Active Record is able
|
537
|
-
to return to its original, less surprising, behavior.
|
538
|
-
|
539
|
-
This historical behavior can now be opt-ed in via:
|
540
|
-
|
541
|
-
```
|
542
|
-
Rails.application.config.active_record.commit_transaction_on_non_local_return = true
|
543
|
-
```
|
544
|
-
|
545
|
-
And is the default for new applications created in Rails 7.1.
|
546
|
-
|
547
|
-
*Jean Boussier*
|
548
|
-
|
549
|
-
* Deprecate `name` argument on `#remove_connection`.
|
550
|
-
|
551
|
-
The `name` argument is deprecated on `#remove_connection` without replacement. `#remove_connection` should be called directly on the class that established the connection.
|
552
|
-
|
553
|
-
*Eileen M. Uchitelle*
|
554
|
-
|
555
|
-
* Fix has_one through singular building with inverse.
|
556
|
-
|
557
|
-
Allows building of records from an association with a has_one through a
|
558
|
-
singular association with inverse. For belongs_to through associations,
|
559
|
-
linking the foreign key to the primary key model isn't needed.
|
560
|
-
For has_one, we cannot build records due to the association not being mutable.
|
561
|
-
|
562
|
-
*Gannon McGibbon*
|
563
|
-
|
564
|
-
* Disable database prepared statements when query logs are enabled
|
565
|
-
|
566
|
-
Prepared Statements and Query Logs are incompatible features due to query logs making every query unique.
|
567
|
-
|
568
|
-
*zzak, Jean Boussier*
|
569
|
-
|
570
|
-
* Support decrypting data encrypted non-deterministically with a SHA1 hash digest.
|
571
|
-
|
572
|
-
This adds a new Active Record encryption option to support decrypting data encrypted
|
573
|
-
non-deterministically with a SHA1 hash digest:
|
574
|
-
|
575
|
-
```
|
576
|
-
Rails.application.config.active_record.encryption.support_sha1_for_non_deterministic_encryption = true
|
577
|
-
```
|
578
|
-
|
579
|
-
The new option addresses a problem when upgrading from 7.0 to 7.1. Due to a bug in how Active Record
|
580
|
-
Encryption was getting initialized, the key provider used for non-deterministic encryption were using
|
581
|
-
SHA-1 as its digest class, instead of the one configured globally by Rails via
|
582
|
-
`Rails.application.config.active_support.key_generator_hash_digest_class`.
|
583
|
-
|
584
|
-
*Cadu Ribeiro and Jorge Manrubia*
|
585
|
-
|
586
|
-
* Added PostgreSQL migration commands for enum rename, add value, and rename value.
|
587
|
-
|
588
|
-
`rename_enum` and `rename_enum_value` are reversible. Due to Postgres
|
589
|
-
limitation, `add_enum_value` is not reversible since you cannot delete enum
|
590
|
-
values. As an alternative you should drop and recreate the enum entirely.
|
591
|
-
|
592
|
-
```ruby
|
593
|
-
rename_enum :article_status, to: :article_state
|
594
|
-
```
|
595
|
-
|
596
|
-
```ruby
|
597
|
-
add_enum_value :article_state, "archived" # will be at the end of existing values
|
598
|
-
add_enum_value :article_state, "in review", before: "published"
|
599
|
-
add_enum_value :article_state, "approved", after: "in review"
|
600
|
-
```
|
601
|
-
|
602
|
-
```ruby
|
603
|
-
rename_enum_value :article_state, from: "archived", to: "deleted"
|
604
|
-
```
|
605
|
-
|
606
|
-
*Ray Faddis*
|
607
|
-
|
608
|
-
* Allow composite primary key to be derived from schema
|
609
|
-
|
610
|
-
Booting an application with a schema that contains composite primary keys
|
611
|
-
will not issue warning and won't `nil`ify the `ActiveRecord::Base#primary_key` value anymore.
|
612
|
-
|
613
|
-
Given a `travel_routes` table definition and a `TravelRoute` model like:
|
614
|
-
```ruby
|
615
|
-
create_table :travel_routes, primary_key: [:origin, :destination], force: true do |t|
|
616
|
-
t.string :origin
|
617
|
-
t.string :destination
|
618
|
-
end
|
619
|
-
|
620
|
-
class TravelRoute < ActiveRecord::Base; end
|
621
|
-
```
|
622
|
-
The `TravelRoute.primary_key` value will be automatically derived to `["origin", "destination"]`
|
623
|
-
|
624
|
-
*Nikita Vasilevsky*
|
625
|
-
|
626
|
-
* Include the `connection_pool` with exceptions raised from an adapter.
|
627
|
-
|
628
|
-
The `connection_pool` provides added context such as the connection used
|
629
|
-
that led to the exception as well as which role and shard.
|
630
|
-
|
631
|
-
*Luan Vieira*
|
632
|
-
|
633
|
-
* Support multiple column ordering for `find_each`, `find_in_batches` and `in_batches`.
|
634
|
-
|
635
|
-
When find_each/find_in_batches/in_batches are performed on a table with composite primary keys, ascending or descending order can be selected for each key.
|
636
|
-
|
637
|
-
```ruby
|
638
|
-
Person.find_each(order: [:desc, :asc]) do |person|
|
639
|
-
person.party_all_night!
|
640
|
-
end
|
641
|
-
```
|
642
|
-
|
643
|
-
*Takuya Kurimoto*
|
644
|
-
|
645
|
-
* Fix where on association with has_one/has_many polymorphic relations.
|
646
|
-
|
647
|
-
Before:
|
648
|
-
```ruby
|
649
|
-
Treasure.where(price_estimates: PriceEstimate.all)
|
650
|
-
#=> SELECT (...) WHERE "treasures"."id" IN (SELECT "price_estimates"."estimate_of_id" FROM "price_estimates")
|
651
|
-
```
|
652
|
-
|
653
|
-
Later:
|
654
|
-
```ruby
|
655
|
-
Treasure.where(price_estimates: PriceEstimate.all)
|
656
|
-
#=> SELECT (...) WHERE "treasures"."id" IN (SELECT "price_estimates"."estimate_of_id" FROM "price_estimates" WHERE "price_estimates"."estimate_of_type" = 'Treasure')
|
657
|
-
```
|
658
|
-
|
659
|
-
*Lázaro Nixon*
|
660
|
-
|
661
|
-
* Assign auto populated columns on Active Record record creation.
|
662
|
-
|
663
|
-
Changes record creation logic to allow for the `auto_increment` column to be assigned
|
664
|
-
immediately after creation regardless of it's relation to the model's primary key.
|
665
|
-
|
666
|
-
The PostgreSQL adapter benefits the most from the change allowing for any number of auto-populated
|
667
|
-
columns to be assigned on the object immediately after row insertion utilizing the `RETURNING` statement.
|
668
|
-
|
669
|
-
*Nikita Vasilevsky*
|
670
|
-
|
671
|
-
* Use the first key in the `shards` hash from `connected_to` for the `default_shard`.
|
672
|
-
|
673
|
-
Some applications may not want to use `:default` as a shard name in their connection model. Unfortunately Active Record expects there to be a `:default` shard because it must assume a shard to get the right connection from the pool manager. Rather than force applications to manually set this, `connects_to` can infer the default shard name from the hash of shards and will now assume that the first shard is your default.
|
674
|
-
|
675
|
-
For example if your model looked like this:
|
676
|
-
|
677
|
-
```ruby
|
678
|
-
class ShardRecord < ApplicationRecord
|
679
|
-
self.abstract_class = true
|
680
|
-
|
681
|
-
connects_to shards: {
|
682
|
-
shard_one: { writing: :shard_one },
|
683
|
-
shard_two: { writing: :shard_two }
|
684
|
-
}
|
685
|
-
```
|
686
|
-
|
687
|
-
Then the `default_shard` for this class would be set to `shard_one`.
|
688
|
-
|
689
|
-
Fixes: #45390
|
690
|
-
|
691
|
-
*Eileen M. Uchitelle*
|
692
|
-
|
693
|
-
* Fix mutation detection for serialized attributes backed by binary columns.
|
694
|
-
|
695
|
-
*Jean Boussier*
|
696
|
-
|
697
|
-
* Add `ActiveRecord.disconnect_all!` method to immediately close all connections from all pools.
|
698
|
-
|
699
|
-
*Jean Boussier*
|
700
|
-
|
701
|
-
* Discard connections which may have been left in a transaction.
|
702
|
-
|
703
|
-
There are cases where, due to an error, `within_new_transaction` may unexpectedly leave a connection in an open transaction. In these cases the connection may be reused, and the following may occur:
|
704
|
-
- Writes appear to fail when they actually succeed.
|
705
|
-
- Writes appear to succeed when they actually fail.
|
706
|
-
- Reads return stale or uncommitted data.
|
707
|
-
|
708
|
-
Previously, the following case was detected:
|
709
|
-
- An error is encountered during the transaction, then another error is encountered while attempting to roll it back.
|
710
|
-
|
711
|
-
Now, the following additional cases are detected:
|
712
|
-
- An error is encountered just after successfully beginning a transaction.
|
713
|
-
- An error is encountered while committing a transaction, then another error is encountered while attempting to roll it back.
|
714
|
-
- An error is encountered while rolling back a transaction.
|
715
|
-
|
716
|
-
*Nick Dower*
|
717
|
-
|
718
|
-
* Active Record query cache now evicts least recently used entries
|
719
|
-
|
720
|
-
By default it only keeps the `100` most recently used queries.
|
721
|
-
|
722
|
-
The cache size can be configured via `database.yml`
|
723
|
-
|
724
|
-
```yaml
|
725
|
-
development:
|
726
|
-
adapter: mysql2
|
727
|
-
query_cache: 200
|
728
|
-
```
|
729
|
-
|
730
|
-
It can also be entirely disabled:
|
731
|
-
|
732
|
-
```yaml
|
733
|
-
development:
|
734
|
-
adapter: mysql2
|
735
|
-
query_cache: false
|
736
|
-
```
|
737
|
-
|
738
|
-
*Jean Boussier*
|
739
|
-
|
740
|
-
* Deprecate `check_pending!` in favor of `check_all_pending!`.
|
741
|
-
|
742
|
-
`check_pending!` will only check for pending migrations on the current database connection or the one passed in. This has been deprecated in favor of `check_all_pending!` which will find all pending migrations for the database configurations in a given environment.
|
743
|
-
|
744
|
-
*Eileen M. Uchitelle*
|
745
|
-
|
746
|
-
* Make `increment_counter`/`decrement_counter` accept an amount argument
|
747
|
-
|
748
|
-
```ruby
|
749
|
-
Post.increment_counter(:comments_count, 5, by: 3)
|
750
|
-
```
|
751
|
-
|
752
|
-
*fatkodima*
|
753
|
-
|
754
|
-
* Add support for `Array#intersect?` to `ActiveRecord::Relation`.
|
755
|
-
|
756
|
-
`Array#intersect?` is only available on Ruby 3.1 or later.
|
757
|
-
|
758
|
-
This allows the Rubocop `Style/ArrayIntersect` cop to work with `ActiveRecord::Relation` objects.
|
759
|
-
|
760
|
-
*John Harry Kelly*
|
761
|
-
|
762
|
-
* The deferrable foreign key can be passed to `t.references`.
|
763
|
-
|
764
|
-
*Hiroyuki Ishii*
|
765
|
-
|
766
|
-
* Deprecate `deferrable: true` option of `add_foreign_key`.
|
767
|
-
|
768
|
-
`deferrable: true` is deprecated in favor of `deferrable: :immediate`, and
|
769
|
-
will be removed in Rails 7.2.
|
770
|
-
|
771
|
-
Because `deferrable: true` and `deferrable: :deferred` are hard to understand.
|
772
|
-
Both true and :deferred are truthy values.
|
773
|
-
This behavior is the same as the deferrable option of the add_unique_key method, added in #46192.
|
774
|
-
|
775
|
-
*Hiroyuki Ishii*
|
776
|
-
|
777
|
-
* `AbstractAdapter#execute` and `#exec_query` now clear the query cache
|
778
|
-
|
779
|
-
If you need to perform a read only SQL query without clearing the query
|
780
|
-
cache, use `AbstractAdapter#select_all`.
|
781
|
-
|
782
|
-
*Jean Boussier*
|
783
|
-
|
784
|
-
* Make `.joins` / `.left_outer_joins` work with CTEs.
|
785
|
-
|
786
|
-
For example:
|
787
|
-
|
788
|
-
```ruby
|
789
|
-
Post
|
790
|
-
.with(commented_posts: Comment.select(:post_id).distinct)
|
791
|
-
.joins(:commented_posts)
|
792
|
-
#=> WITH (...) SELECT ... INNER JOIN commented_posts on posts.id = commented_posts.post_id
|
793
|
-
```
|
794
|
-
|
795
|
-
*Vladimir Dementyev*
|
796
|
-
|
797
|
-
* Add a load hook for `ActiveRecord::ConnectionAdapters::Mysql2Adapter`
|
798
|
-
(named `active_record_mysql2adapter`) to allow for overriding aspects of the
|
799
|
-
`ActiveRecord::ConnectionAdapters::Mysql2Adapter` class. This makes `Mysql2Adapter`
|
800
|
-
consistent with `PostgreSQLAdapter` and `SQLite3Adapter` that already have load hooks.
|
801
|
-
|
802
|
-
*fatkodima*
|
803
|
-
|
804
|
-
* Introduce adapter for Trilogy database client
|
805
|
-
|
806
|
-
Trilogy is a MySQL-compatible database client. Rails applications can use Trilogy
|
807
|
-
by configuring their `config/database.yml`:
|
808
|
-
|
809
|
-
```yaml
|
810
|
-
development:
|
811
|
-
adapter: trilogy
|
812
|
-
database: blog_development
|
813
|
-
pool: 5
|
814
|
-
```
|
815
|
-
|
816
|
-
Or by using the `DATABASE_URL` environment variable:
|
817
|
-
|
818
|
-
```ruby
|
819
|
-
ENV['DATABASE_URL'] # => "trilogy://localhost/blog_development?pool=5"
|
820
|
-
```
|
821
|
-
|
822
|
-
*Adrianna Chang*
|
823
|
-
|
824
|
-
* `after_commit` callbacks defined on models now execute in the correct order.
|
825
|
-
|
826
|
-
```ruby
|
827
|
-
class User < ActiveRecord::Base
|
828
|
-
after_commit { puts("this gets called first") }
|
829
|
-
after_commit { puts("this gets called second") }
|
830
|
-
end
|
831
|
-
```
|
832
|
-
|
833
|
-
Previously, the callbacks executed in the reverse order. To opt in to the new behaviour:
|
834
|
-
|
835
|
-
```ruby
|
836
|
-
config.active_record.run_after_transaction_callbacks_in_order_defined = true
|
837
|
-
```
|
838
|
-
|
839
|
-
This is the default for new apps.
|
840
|
-
|
841
|
-
*Alex Ghiculescu*
|
842
|
-
|
843
|
-
* Infer `foreign_key` when `inverse_of` is present on `has_one` and `has_many` associations.
|
844
|
-
|
845
|
-
```ruby
|
846
|
-
has_many :citations, foreign_key: "book1_id", inverse_of: :book
|
847
|
-
```
|
848
|
-
|
849
|
-
can be simplified to
|
850
|
-
|
851
|
-
```ruby
|
852
|
-
has_many :citations, inverse_of: :book
|
853
|
-
```
|
854
|
-
|
855
|
-
and the foreign_key will be read from the corresponding `belongs_to` association.
|
856
|
-
|
857
|
-
*Daniel Whitney*
|
858
|
-
|
859
|
-
* Limit max length of auto generated index names
|
860
|
-
|
861
|
-
Auto generated index names are now limited to 62 bytes, which fits within
|
862
|
-
the default index name length limits for MySQL, Postgres and SQLite.
|
863
|
-
|
864
|
-
Any index name over the limit will fallback to the new short format.
|
865
|
-
|
866
|
-
Before (too long):
|
867
|
-
```
|
868
|
-
index_testings_on_foo_and_bar_and_first_name_and_last_name_and_administrator
|
869
|
-
```
|
870
|
-
|
871
|
-
After (short format):
|
872
|
-
```
|
873
|
-
idx_on_foo_bar_first_name_last_name_administrator_5939248142
|
874
|
-
```
|
875
|
-
|
876
|
-
The short format includes a hash to ensure the name is unique database-wide.
|
877
|
-
|
878
|
-
*Mike Coutermarsh*
|
879
|
-
|
880
|
-
* Introduce a more stable and optimized Marshal serializer for Active Record models.
|
881
|
-
|
882
|
-
Can be enabled with `config.active_record.marshalling_format_version = 7.1`.
|
883
|
-
|
884
|
-
*Jean Boussier*
|
885
|
-
|
886
|
-
* Allow specifying where clauses with column-tuple syntax.
|
887
|
-
|
888
|
-
Querying through `#where` now accepts a new tuple-syntax which accepts, as
|
889
|
-
a key, an array of columns and, as a value, an array of corresponding tuples.
|
890
|
-
The key specifies a list of columns, while the value is an array of
|
891
|
-
ordered-tuples that conform to the column list.
|
892
|
-
|
893
|
-
For instance:
|
894
|
-
|
895
|
-
```ruby
|
896
|
-
# Cpk::Book => Cpk::Book(author_id: integer, number: integer, title: string, revision: integer)
|
897
|
-
# Cpk::Book.primary_key => ["author_id", "number"]
|
898
|
-
|
899
|
-
book = Cpk::Book.create!(author_id: 1, number: 1)
|
900
|
-
Cpk::Book.where(Cpk::Book.primary_key => [[1, 2]]) # => [book]
|
901
|
-
|
902
|
-
# Topic => Topic(id: integer, title: string, author_name: string...)
|
903
|
-
|
904
|
-
Topic.where([:title, :author_name] => [["The Alchemist", "Paulo Coelho"], ["Harry Potter", "J.K Rowling"]])
|
905
|
-
```
|
906
|
-
|
907
|
-
*Paarth Madan*
|
908
|
-
|
909
|
-
* Allow warning codes to be ignore when reporting SQL warnings.
|
910
|
-
|
911
|
-
Active Record config that can ignore warning codes
|
912
|
-
|
913
|
-
```ruby
|
914
|
-
# Configure allowlist of warnings that should always be ignored
|
915
|
-
config.active_record.db_warnings_ignore = [
|
916
|
-
"1062", # MySQL Error 1062: Duplicate entry
|
917
|
-
]
|
918
|
-
```
|
919
|
-
|
920
|
-
This is supported for the MySQL and PostgreSQL adapters.
|
921
|
-
|
922
|
-
*Nick Borromeo*
|
923
|
-
|
924
|
-
* Introduce `:active_record_fixtures` lazy load hook.
|
925
|
-
|
926
|
-
Hooks defined with this name will be run whenever `TestFixtures` is included
|
927
|
-
in a class.
|
928
|
-
|
929
|
-
```ruby
|
930
|
-
ActiveSupport.on_load(:active_record_fixtures) do
|
931
|
-
self.fixture_paths << "test/fixtures"
|
932
|
-
end
|
933
|
-
|
934
|
-
klass = Class.new
|
935
|
-
klass.include(ActiveRecord::TestFixtures)
|
936
|
-
|
937
|
-
klass.fixture_paths # => ["test/fixtures"]
|
938
|
-
```
|
939
|
-
|
940
|
-
*Andrew Novoselac*
|
941
|
-
|
942
|
-
* Introduce `TestFixtures#fixture_paths`.
|
943
|
-
|
944
|
-
Multiple fixture paths can now be specified using the `#fixture_paths` accessor.
|
945
|
-
Apps will continue to have `test/fixtures` as their one fixture path by default,
|
946
|
-
but additional fixture paths can be specified.
|
947
|
-
|
948
|
-
```ruby
|
949
|
-
ActiveSupport::TestCase.fixture_paths << "component1/test/fixtures"
|
950
|
-
ActiveSupport::TestCase.fixture_paths << "component2/test/fixtures"
|
951
|
-
```
|
952
|
-
|
953
|
-
`TestFixtures#fixture_path` is now deprecated.
|
954
|
-
|
955
|
-
*Andrew Novoselac*
|
956
|
-
|
957
|
-
* Adds support for deferrable exclude constraints in PostgreSQL.
|
958
|
-
|
959
|
-
By default, exclude constraints in PostgreSQL are checked after each statement.
|
960
|
-
This works for most use cases, but becomes a major limitation when replacing
|
961
|
-
records with overlapping ranges by using multiple statements.
|
962
|
-
|
963
|
-
```ruby
|
964
|
-
exclusion_constraint :users, "daterange(valid_from, valid_to) WITH &&", deferrable: :immediate
|
965
|
-
```
|
966
|
-
|
967
|
-
Passing `deferrable: :immediate` checks constraint after each statement,
|
968
|
-
but allows manually deferring the check using `SET CONSTRAINTS ALL DEFERRED`
|
969
|
-
within a transaction. This will cause the excludes to be checked after the transaction.
|
970
|
-
|
971
|
-
It's also possible to change the default behavior from an immediate check
|
972
|
-
(after the statement), to a deferred check (after the transaction):
|
973
|
-
|
974
|
-
```ruby
|
975
|
-
exclusion_constraint :users, "daterange(valid_from, valid_to) WITH &&", deferrable: :deferred
|
976
|
-
```
|
977
|
-
|
978
|
-
*Hiroyuki Ishii*
|
979
|
-
|
980
|
-
* Respect `foreign_type` option to `delegated_type` for `{role}_class` method.
|
981
|
-
|
982
|
-
Usage of `delegated_type` with non-conventional `{role}_type` column names can now be specified with `foreign_type` option.
|
983
|
-
This option is the same as `foreign_type` as forwarded to the underlying `belongs_to` association that `delegated_type` wraps.
|
984
|
-
|
985
|
-
*Jason Karns*
|
986
|
-
|
987
|
-
* Add support for unique constraints (PostgreSQL-only).
|
988
|
-
|
989
|
-
```ruby
|
990
|
-
add_unique_key :sections, [:position], deferrable: :deferred, name: "unique_section_position"
|
991
|
-
remove_unique_key :sections, name: "unique_section_position"
|
992
|
-
```
|
993
|
-
|
994
|
-
See PostgreSQL's [Unique Constraints](https://www.postgresql.org/docs/current/ddl-constraints.html#DDL-CONSTRAINTS-UNIQUE-CONSTRAINTS) documentation for more on unique constraints.
|
995
|
-
|
996
|
-
By default, unique constraints in PostgreSQL are checked after each statement.
|
997
|
-
This works for most use cases, but becomes a major limitation when replacing
|
998
|
-
records with unique column by using multiple statements.
|
999
|
-
|
1000
|
-
An example of swapping unique columns between records.
|
1001
|
-
|
1002
|
-
```ruby
|
1003
|
-
# position is unique column
|
1004
|
-
old_item = Item.create!(position: 1)
|
1005
|
-
new_item = Item.create!(position: 2)
|
1006
|
-
|
1007
|
-
Item.transaction do
|
1008
|
-
old_item.update!(position: 2)
|
1009
|
-
new_item.update!(position: 1)
|
1010
|
-
end
|
1011
|
-
```
|
1012
|
-
|
1013
|
-
Using the default behavior, the transaction would fail when executing the
|
1014
|
-
first `UPDATE` statement.
|
1015
|
-
|
1016
|
-
By passing the `:deferrable` option to the `add_unique_key` statement in
|
1017
|
-
migrations, it's possible to defer this check.
|
1018
|
-
|
1019
|
-
```ruby
|
1020
|
-
add_unique_key :items, [:position], deferrable: :immediate
|
1021
|
-
```
|
1022
|
-
|
1023
|
-
Passing `deferrable: :immediate` does not change the behaviour of the previous example,
|
1024
|
-
but allows manually deferring the check using `SET CONSTRAINTS ALL DEFERRED` within a transaction.
|
1025
|
-
This will cause the unique constraints to be checked after the transaction.
|
1026
|
-
|
1027
|
-
It's also possible to adjust the default behavior from an immediate
|
1028
|
-
check (after the statement), to a deferred check (after the transaction):
|
1029
|
-
|
1030
|
-
```ruby
|
1031
|
-
add_unique_key :items, [:position], deferrable: :deferred
|
1032
|
-
```
|
1033
|
-
|
1034
|
-
If you want to change an existing unique index to deferrable, you can use :using_index
|
1035
|
-
to create deferrable unique constraints.
|
1036
|
-
|
1037
|
-
```ruby
|
1038
|
-
add_unique_key :items, deferrable: :deferred, using_index: "index_items_on_position"
|
1039
|
-
```
|
1040
|
-
|
1041
|
-
*Hiroyuki Ishii*
|
1042
|
-
|
1043
|
-
* Remove deprecated `Tasks::DatabaseTasks.schema_file_type`.
|
1044
|
-
|
1045
|
-
*Rafael Mendonça França*
|
1046
|
-
|
1047
|
-
* Remove deprecated `config.active_record.partial_writes`.
|
1048
|
-
|
1049
|
-
*Rafael Mendonça França*
|
1050
|
-
|
1051
|
-
* Remove deprecated `ActiveRecord::Base` config accessors.
|
1052
|
-
|
1053
|
-
*Rafael Mendonça França*
|
1054
|
-
|
1055
|
-
* Remove the `:include_replicas` argument from `configs_for`. Use `:include_hidden` argument instead.
|
1056
|
-
|
1057
|
-
*Eileen M. Uchitelle*
|
1058
|
-
|
1059
|
-
* Allow applications to lookup a config via a custom hash key.
|
1060
|
-
|
1061
|
-
If you have registered a custom config or want to find configs where the hash matches a specific key, now you can pass `config_key` to `configs_for`. For example if you have a `db_config` with the key `vitess` you can look up a database configuration hash by matching that key.
|
1062
|
-
|
1063
|
-
```ruby
|
1064
|
-
ActiveRecord::Base.configurations.configs_for(env_name: "development", name: "primary", config_key: :vitess)
|
1065
|
-
ActiveRecord::Base.configurations.configs_for(env_name: "development", config_key: :vitess)
|
1066
|
-
```
|
1067
|
-
|
1068
|
-
*Eileen M. Uchitelle*
|
1069
|
-
|
1070
|
-
* Allow applications to register a custom database configuration handler.
|
1071
|
-
|
1072
|
-
Adds a mechanism for registering a custom handler for cases where you want database configurations to respond to custom methods. This is useful for non-Rails database adapters or tools like Vitess that you may want to configure differently from a standard `HashConfig` or `UrlConfig`.
|
1073
|
-
|
1074
|
-
Given the following database YAML we want the `animals` db to create a `CustomConfig` object instead while the `primary` database will be a `UrlConfig`:
|
1075
|
-
|
1076
|
-
```yaml
|
1077
|
-
development:
|
1078
|
-
primary:
|
1079
|
-
url: postgres://localhost/primary
|
1080
|
-
animals:
|
1081
|
-
url: postgres://localhost/animals
|
1082
|
-
custom_config:
|
1083
|
-
sharded: 1
|
1084
|
-
```
|
1085
|
-
|
1086
|
-
To register a custom handler first make a class that has your custom methods:
|
1087
|
-
|
1088
|
-
```ruby
|
1089
|
-
class CustomConfig < ActiveRecord::DatabaseConfigurations::UrlConfig
|
1090
|
-
def sharded?
|
1091
|
-
custom_config.fetch("sharded", false)
|
1092
|
-
end
|
1093
|
-
|
1094
|
-
private
|
1095
|
-
def custom_config
|
1096
|
-
configuration_hash.fetch(:custom_config)
|
1097
|
-
end
|
1098
|
-
end
|
1099
|
-
```
|
1100
|
-
|
1101
|
-
Then register the config in an initializer:
|
1102
|
-
|
1103
|
-
```ruby
|
1104
|
-
ActiveRecord::DatabaseConfigurations.register_db_config_handler do |env_name, name, url, config|
|
1105
|
-
next unless config.key?(:custom_config)
|
1106
|
-
CustomConfig.new(env_name, name, url, config)
|
1107
|
-
end
|
1108
|
-
```
|
1109
|
-
|
1110
|
-
When the application is booted, configuration hashes with the `:custom_config` key will be `CustomConfig` objects and respond to `sharded?`. Applications must handle the condition in which Active Record should use their custom handler.
|
1111
|
-
|
1112
|
-
*Eileen M. Uchitelle and John Crepezzi*
|
1113
|
-
|
1114
|
-
* `ActiveRecord::Base.serialize` no longer uses YAML by default.
|
1115
|
-
|
1116
|
-
YAML isn't particularly performant and can lead to security issues
|
1117
|
-
if not used carefully.
|
1118
|
-
|
1119
|
-
Unfortunately there isn't really any good serializers in Ruby's stdlib
|
1120
|
-
to replace it.
|
1121
|
-
|
1122
|
-
The obvious choice would be JSON, which is a fine format for this use case,
|
1123
|
-
however the JSON serializer in Ruby's stdlib isn't strict enough, as it fallback
|
1124
|
-
to casting unknown types to strings, which could lead to corrupted data.
|
1125
|
-
|
1126
|
-
Some third party JSON libraries like `Oj` have a suitable strict mode.
|
1127
|
-
|
1128
|
-
So it's preferable that users choose a serializer based on their own constraints.
|
1129
|
-
|
1130
|
-
The original default can be restored by setting `config.active_record.default_column_serializer = YAML`.
|
1131
|
-
|
1132
|
-
*Jean Boussier*
|
1133
|
-
|
1134
|
-
* `ActiveRecord::Base.serialize` signature changed.
|
1135
|
-
|
1136
|
-
Rather than a single positional argument that accepts two possible
|
1137
|
-
types of values, `serialize` now accepts two distinct keyword arguments.
|
1138
|
-
|
1139
|
-
Before:
|
1140
|
-
|
1141
|
-
```ruby
|
1142
|
-
serialize :content, JSON
|
1143
|
-
serialize :backtrace, Array
|
1144
|
-
```
|
1145
|
-
|
1146
|
-
After:
|
1147
|
-
|
1148
|
-
```ruby
|
1149
|
-
serialize :content, coder: JSON
|
1150
|
-
serialize :backtrace, type: Array
|
1151
|
-
```
|
1152
|
-
|
1153
|
-
*Jean Boussier*
|
1154
|
-
|
1155
|
-
* YAML columns use `YAML.safe_dump` if available.
|
1156
|
-
|
1157
|
-
As of `psych 5.1.0`, `YAML.safe_dump` can now apply the same permitted
|
1158
|
-
types restrictions than `YAML.safe_load`.
|
1159
|
-
|
1160
|
-
It's preferable to ensure the payload only use allowed types when we first
|
1161
|
-
try to serialize it, otherwise you may end up with invalid records in the
|
1162
|
-
database.
|
1163
|
-
|
1164
|
-
*Jean Boussier*
|
1165
|
-
|
1166
|
-
* `ActiveRecord::QueryLogs` better handle broken encoding.
|
1167
|
-
|
1168
|
-
It's not uncommon when building queries with BLOB fields to contain
|
1169
|
-
binary data. Unless the call carefully encode the string in ASCII-8BIT
|
1170
|
-
it generally end up being encoded in `UTF-8`, and `QueryLogs` would
|
1171
|
-
end up failing on it.
|
1172
|
-
|
1173
|
-
`ActiveRecord::QueryLogs` no longer depend on the query to be properly encoded.
|
1174
|
-
|
1175
|
-
*Jean Boussier*
|
1176
|
-
|
1177
|
-
* Fix a bug where `ActiveRecord::Generators::ModelGenerator` would not respect create_table_migration template overrides.
|
1178
|
-
|
1179
|
-
```
|
1180
|
-
rails g model create_books title:string content:text
|
1181
|
-
```
|
1182
|
-
will now read from the create_table_migration.rb.tt template in the following locations in order:
|
1183
|
-
```
|
1184
|
-
lib/templates/active_record/model/create_table_migration.rb
|
1185
|
-
lib/templates/active_record/migration/create_table_migration.rb
|
1186
|
-
```
|
1187
|
-
|
1188
|
-
*Spencer Neste*
|
1189
|
-
|
1190
|
-
* `ActiveRecord::Relation#explain` now accepts options.
|
1191
|
-
|
1192
|
-
For databases and adapters which support them (currently PostgreSQL
|
1193
|
-
and MySQL), options can be passed to `explain` to provide more
|
1194
|
-
detailed query plan analysis:
|
1195
|
-
|
1196
|
-
```ruby
|
1197
|
-
Customer.where(id: 1).joins(:orders).explain(:analyze, :verbose)
|
1198
|
-
```
|
1199
|
-
|
1200
|
-
*Reid Lynch*
|
1201
|
-
|
1202
|
-
* Multiple `Arel::Nodes::SqlLiteral` nodes can now be added together to
|
1203
|
-
form `Arel::Nodes::Fragments` nodes. This allows joining several pieces
|
1204
|
-
of SQL.
|
1205
|
-
|
1206
|
-
*Matthew Draper*, *Ole Friis*
|
1207
|
-
|
1208
|
-
* `ActiveRecord::Base#signed_id` raises if called on a new record.
|
1209
|
-
|
1210
|
-
Previously it would return an ID that was not usable, since it was based on `id = nil`.
|
1211
|
-
|
1212
|
-
*Alex Ghiculescu*
|
1213
|
-
|
1214
|
-
* Allow SQL warnings to be reported.
|
1215
|
-
|
1216
|
-
Active Record configs can be set to enable SQL warning reporting.
|
1217
|
-
|
1218
|
-
```ruby
|
1219
|
-
# Configure action to take when SQL query produces warning
|
1220
|
-
config.active_record.db_warnings_action = :raise
|
1221
|
-
|
1222
|
-
# Configure allowlist of warnings that should always be ignored
|
1223
|
-
config.active_record.db_warnings_ignore = [
|
1224
|
-
/Invalid utf8mb4 character string/,
|
1225
|
-
"An exact warning message",
|
1226
|
-
]
|
1227
|
-
```
|
1228
|
-
|
1229
|
-
This is supported for the MySQL and PostgreSQL adapters.
|
1230
|
-
|
1231
|
-
*Adrianna Chang*, *Paarth Madan*
|
1232
|
-
|
1233
|
-
* Add `#regroup` query method as a short-hand for `.unscope(:group).group(fields)`
|
1234
|
-
|
1235
|
-
Example:
|
1236
|
-
|
1237
|
-
```ruby
|
1238
|
-
Post.group(:title).regroup(:author)
|
1239
|
-
# SELECT `posts`.`*` FROM `posts` GROUP BY `posts`.`author`
|
1240
|
-
```
|
1241
|
-
|
1242
|
-
*Danielius Visockas*
|
1243
|
-
|
1244
|
-
* PostgreSQL adapter method `enable_extension` now allows parameter to be `[schema_name.]<extension_name>`
|
1245
|
-
if the extension must be installed on another schema.
|
1246
|
-
|
1247
|
-
Example: `enable_extension('heroku_ext.hstore')`
|
1248
|
-
|
1249
|
-
*Leonardo Luarte*
|
1250
|
-
|
1251
|
-
* Add `:include` option to `add_index`.
|
1252
|
-
|
1253
|
-
Add support for including non-key columns in indexes for PostgreSQL
|
1254
|
-
with the `INCLUDE` parameter.
|
1255
|
-
|
1256
|
-
```ruby
|
1257
|
-
add_index(:users, :email, include: [:id, :created_at])
|
1258
|
-
```
|
1259
|
-
|
1260
|
-
will result in:
|
1261
|
-
|
1262
|
-
```sql
|
1263
|
-
CREATE INDEX index_users_on_email USING btree (email) INCLUDE (id, created_at)
|
1264
|
-
```
|
1265
|
-
|
1266
|
-
*Steve Abrams*
|
1267
|
-
|
1268
|
-
* `ActiveRecord::Relation`’s `#any?`, `#none?`, and `#one?` methods take an optional pattern
|
1269
|
-
argument, more closely matching their `Enumerable` equivalents.
|
1270
|
-
|
1271
|
-
*George Claghorn*
|
1272
|
-
|
1273
|
-
* Add `ActiveRecord::Base.normalizes` for declaring attribute normalizations.
|
1274
|
-
|
1275
|
-
An attribute normalization is applied when the attribute is assigned or
|
1276
|
-
updated, and the normalized value will be persisted to the database. The
|
1277
|
-
normalization is also applied to the corresponding keyword argument of query
|
1278
|
-
methods, allowing records to be queried using unnormalized values.
|
1279
|
-
|
1280
|
-
For example:
|
1281
|
-
|
1282
|
-
```ruby
|
1283
|
-
class User < ActiveRecord::Base
|
1284
|
-
normalizes :email, with: -> email { email.strip.downcase }
|
1285
|
-
normalizes :phone, with: -> phone { phone.delete("^0-9").delete_prefix("1") }
|
1286
|
-
end
|
1287
|
-
|
1288
|
-
user = User.create(email: " CRUISE-CONTROL@EXAMPLE.COM\n")
|
1289
|
-
user.email # => "cruise-control@example.com"
|
1290
|
-
|
1291
|
-
user = User.find_by(email: "\tCRUISE-CONTROL@EXAMPLE.COM ")
|
1292
|
-
user.email # => "cruise-control@example.com"
|
1293
|
-
user.email_before_type_cast # => "cruise-control@example.com"
|
1294
|
-
|
1295
|
-
User.where(email: "\tCRUISE-CONTROL@EXAMPLE.COM ").count # => 1
|
1296
|
-
User.where(["email = ?", "\tCRUISE-CONTROL@EXAMPLE.COM "]).count # => 0
|
1297
|
-
|
1298
|
-
User.exists?(email: "\tCRUISE-CONTROL@EXAMPLE.COM ") # => true
|
1299
|
-
User.exists?(["email = ?", "\tCRUISE-CONTROL@EXAMPLE.COM "]) # => false
|
1300
|
-
|
1301
|
-
User.normalize_value_for(:phone, "+1 (555) 867-5309") # => "5558675309"
|
1302
|
-
```
|
1303
|
-
|
1304
|
-
*Jonathan Hefner*
|
1305
|
-
|
1306
|
-
* Hide changes to before_committed! callback behaviour behind flag.
|
1307
|
-
|
1308
|
-
In #46525, behavior around before_committed! callbacks was changed so that callbacks
|
1309
|
-
would run on every enrolled record in a transaction, not just the first copy of a record.
|
1310
|
-
This change in behavior is now controlled by a configuration option,
|
1311
|
-
`config.active_record.before_committed_on_all_records`. It will be enabled by default on Rails 7.1.
|
1312
|
-
|
1313
|
-
*Adrianna Chang*
|
1314
|
-
|
1315
|
-
* The `namespaced_controller` Query Log tag now matches the `controller` format
|
1316
|
-
|
1317
|
-
For example, a request processed by `NameSpaced::UsersController` will now log as:
|
1318
|
-
|
1319
|
-
```
|
1320
|
-
:controller # "users"
|
1321
|
-
:namespaced_controller # "name_spaced/users"
|
1322
|
-
```
|
1323
|
-
|
1324
|
-
*Alex Ghiculescu*
|
1325
|
-
|
1326
|
-
* Return only unique ids from ActiveRecord::Calculations#ids
|
1327
|
-
|
1328
|
-
Updated ActiveRecord::Calculations#ids to only return the unique ids of the base model
|
1329
|
-
when using eager_load, preload and includes.
|
1330
|
-
|
1331
|
-
```ruby
|
1332
|
-
Post.find_by(id: 1).comments.count
|
1333
|
-
# => 5
|
1334
|
-
Post.includes(:comments).where(id: 1).pluck(:id)
|
1335
|
-
# => [1, 1, 1, 1, 1]
|
1336
|
-
Post.includes(:comments).where(id: 1).ids
|
1337
|
-
# => [1]
|
1338
|
-
```
|
1339
|
-
|
1340
|
-
*Joshua Young*
|
1341
|
-
|
1342
|
-
* Stop using `LOWER()` for case-insensitive queries on `citext` columns
|
1343
|
-
|
1344
|
-
Previously, `LOWER()` was added for e.g. uniqueness validations with
|
1345
|
-
`case_sensitive: false`.
|
1346
|
-
It wasn't mentioned in the documentation that the index without `LOWER()`
|
1347
|
-
wouldn't be used in this case.
|
1348
|
-
|
1349
|
-
*Phil Pirozhkov*
|
1350
|
-
|
1351
|
-
* Extract `#sync_timezone_changes` method in AbstractMysqlAdapter to enable subclasses
|
1352
|
-
to sync database timezone changes without overriding `#raw_execute`.
|
1353
|
-
|
1354
|
-
*Adrianna Chang*, *Paarth Madan*
|
1355
|
-
|
1356
|
-
* Do not write additional new lines when dumping sql migration versions
|
1357
|
-
|
1358
|
-
This change updates the `insert_versions_sql` function so that the database insert string containing the current database migration versions does not end with two additional new lines.
|
1359
|
-
|
1360
|
-
*Misha Schwartz*
|
1361
|
-
|
1362
|
-
* Fix `composed_of` value freezing and duplication.
|
1363
|
-
|
1364
|
-
Previously composite values exhibited two confusing behaviors:
|
1365
|
-
|
1366
|
-
- When reading a compositve value it'd _NOT_ be frozen, allowing it to get out of sync with its underlying database
|
1367
|
-
columns.
|
1368
|
-
- When writing a compositve value the argument would be frozen, potentially confusing the caller.
|
1369
|
-
|
1370
|
-
Currently, composite values instantiated based on database columns are frozen (addressing the first issue) and
|
1371
|
-
assigned compositve values are duplicated and the duplicate is frozen (addressing the second issue).
|
1372
|
-
|
1373
|
-
*Greg Navis*
|
1374
|
-
|
1375
|
-
* Fix redundant updates to the column insensitivity cache
|
1376
|
-
|
1377
|
-
Fixed redundant queries checking column capability for insensitive
|
1378
|
-
comparison.
|
1379
|
-
|
1380
|
-
*Phil Pirozhkov*
|
1381
|
-
|
1382
|
-
* Allow disabling methods generated by `ActiveRecord.enum`.
|
1383
|
-
|
1384
|
-
*Alfred Dominic*
|
1385
|
-
|
1386
|
-
* Avoid validating `belongs_to` association if it has not changed.
|
1387
|
-
|
1388
|
-
Previously, when updating a record, Active Record will perform an extra query to check for the presence of
|
1389
|
-
`belongs_to` associations (if the presence is configured to be mandatory), even if that attribute hasn't changed.
|
1390
|
-
|
1391
|
-
Currently, only `belongs_to`-related columns are checked for presence. It is possible to have orphaned records with
|
1392
|
-
this approach. To avoid this problem, you need to use a foreign key.
|
1393
|
-
|
1394
|
-
This behavior can be controlled by configuration:
|
1395
|
-
|
1396
|
-
```ruby
|
1397
|
-
config.active_record.belongs_to_required_validates_foreign_key = false
|
1398
|
-
```
|
1399
|
-
|
1400
|
-
and will be disabled by default with `config.load_defaults 7.1`.
|
1401
|
-
|
1402
|
-
*fatkodima*
|
1403
|
-
|
1404
|
-
* `has_one` and `belongs_to` associations now define a `reset_association` method
|
1405
|
-
on the owner model (where `association` is the name of the association). This
|
1406
|
-
method unloads the cached associate record, if any, and causes the next access
|
1407
|
-
to query it from the database.
|
1408
|
-
|
1409
|
-
*George Claghorn*
|
1410
|
-
|
1411
|
-
* Allow per attribute setting of YAML permitted classes (safe load) and unsafe load.
|
1412
|
-
|
1413
|
-
*Carlos Palhares*
|
1414
|
-
|
1415
|
-
* Add a build persistence method
|
1416
|
-
|
1417
|
-
Provides a wrapper for `new`, to provide feature parity with `create`s
|
1418
|
-
ability to create multiple records from an array of hashes, using the
|
1419
|
-
same notation as the `build` method on associations.
|
1420
|
-
|
1421
|
-
*Sean Denny*
|
1422
|
-
|
1423
|
-
* Raise on assignment to readonly attributes
|
1424
|
-
|
1425
|
-
```ruby
|
1426
|
-
class Post < ActiveRecord::Base
|
1427
|
-
attr_readonly :content
|
1428
|
-
end
|
1429
|
-
Post.create!(content: "cannot be updated")
|
1430
|
-
post.content # "cannot be updated"
|
1431
|
-
post.content = "something else" # => ActiveRecord::ReadonlyAttributeError
|
1432
|
-
```
|
1433
|
-
|
1434
|
-
Previously, assignment would succeed but silently not write to the database.
|
1435
|
-
|
1436
|
-
This behavior can be controlled by configuration:
|
1437
|
-
|
1438
|
-
```ruby
|
1439
|
-
config.active_record.raise_on_assign_to_attr_readonly = true
|
1440
|
-
```
|
1441
|
-
|
1442
|
-
and will be enabled by default with `config.load_defaults 7.1`.
|
1443
|
-
|
1444
|
-
*Alex Ghiculescu*, *Hartley McGuire*
|
1445
|
-
|
1446
|
-
* Allow unscoping of preload and eager_load associations
|
1447
|
-
|
1448
|
-
Added the ability to unscope preload and eager_load associations just like
|
1449
|
-
includes, joins, etc. See ActiveRecord::QueryMethods::VALID_UNSCOPING_VALUES
|
1450
|
-
for the full list of supported unscopable scopes.
|
1451
|
-
|
1452
|
-
```ruby
|
1453
|
-
query.unscope(:eager_load, :preload).group(:id).select(:id)
|
1454
|
-
```
|
1455
|
-
|
1456
|
-
*David Morehouse*
|
1457
|
-
|
1458
|
-
* Add automatic filtering of encrypted attributes on inspect
|
1459
|
-
|
1460
|
-
This feature is enabled by default but can be disabled with
|
19
|
+
E.g. with the following setup:
|
1461
20
|
|
1462
21
|
```ruby
|
1463
|
-
|
22
|
+
class Nested::Post < ApplicationRecord
|
23
|
+
has_one :post, through: :other
|
24
|
+
end
|
1464
25
|
```
|
1465
26
|
|
1466
|
-
|
1467
|
-
|
1468
|
-
* Clear locking column on #dup
|
1469
|
-
|
1470
|
-
This change fixes not to duplicate locking_column like id and timestamps.
|
27
|
+
Before, `#post` would infer the model as `Nested::Post`, but now it correctly infers `Post`.
|
1471
28
|
|
1472
|
-
|
1473
|
-
car = Car.create!
|
1474
|
-
car.touch
|
1475
|
-
car.lock_version #=> 1
|
1476
|
-
car.dup.lock_version #=> 0
|
1477
|
-
```
|
29
|
+
*Joshua Young*
|
1478
30
|
|
1479
|
-
|
31
|
+
* PostgreSQL `Cidr#change?` detects the address prefix change.
|
1480
32
|
|
1481
|
-
*
|
33
|
+
*Taketo Takashima*
|
1482
34
|
|
1483
|
-
|
1484
|
-
allowing the framework to skip issuing the `ROLLBACK` statement in more cases.
|
1485
|
-
Only affects adapters that have `savepoint_errors_invalidate_transactions?` configured as `true`,
|
1486
|
-
which at this point is only applicable to the `mysql2` adapter.
|
35
|
+
* Change `BatchEnumerator#destroy_all` to return the total number of affected rows.
|
1487
36
|
|
1488
|
-
|
37
|
+
Previously, it always returned `nil`.
|
1489
38
|
|
1490
|
-
*
|
39
|
+
*fatkodima*
|
1491
40
|
|
1492
|
-
|
1493
|
-
updating, deleting or reloading an `ActiveRecord::Base` object
|
41
|
+
* Support `touch_all` in batches.
|
1494
42
|
|
1495
43
|
```ruby
|
1496
|
-
|
1497
|
-
query_constraints :company_id, :id
|
1498
|
-
end
|
1499
|
-
developer = Developer.first.update(name: "Bob")
|
1500
|
-
# => UPDATE "developers" SET "name" = 'Bob' WHERE "developers"."company_id" = 1 AND "developers"."id" = 1
|
44
|
+
Post.in_batches.touch_all
|
1501
45
|
```
|
1502
46
|
|
1503
|
-
*
|
1504
|
-
|
1505
|
-
* Adds `validate` to foreign keys and check constraints in schema.rb
|
1506
|
-
|
1507
|
-
Previously, `schema.rb` would not record if `validate: false` had been used when adding a foreign key or check
|
1508
|
-
constraint, so restoring a database from the schema could result in foreign keys or check constraints being
|
1509
|
-
incorrectly validated.
|
1510
|
-
|
1511
|
-
*Tommy Graves*
|
1512
|
-
|
1513
|
-
* Adapter `#execute` methods now accept an `allow_retry` option. When set to `true`, the SQL statement will be
|
1514
|
-
retried, up to the database's configured `connection_retries` value, upon encountering connection-related errors.
|
1515
|
-
|
1516
|
-
*Adrianna Chang*
|
1517
|
-
|
1518
|
-
* Only trigger `after_commit :destroy` callbacks when a database row is deleted.
|
1519
|
-
|
1520
|
-
This prevents `after_commit :destroy` callbacks from being triggered again
|
1521
|
-
when `destroy` is called multiple times on the same record.
|
1522
|
-
|
1523
|
-
*Ben Sheldon*
|
1524
|
-
|
1525
|
-
* Fix `ciphertext_for` for yet-to-be-encrypted values.
|
1526
|
-
|
1527
|
-
Previously, `ciphertext_for` returned the cleartext of values that had not
|
1528
|
-
yet been encrypted, such as with an unpersisted record:
|
1529
|
-
|
1530
|
-
```ruby
|
1531
|
-
Post.encrypts :body
|
47
|
+
*fatkodima*
|
1532
48
|
|
1533
|
-
|
1534
|
-
post.ciphertext_for(:body)
|
1535
|
-
# => "{\"p\":\"abc..."
|
49
|
+
* Add support for `:if_not_exists` and `:force` options to `create_schema`.
|
1536
50
|
|
1537
|
-
|
1538
|
-
post.ciphertext_for(:body)
|
1539
|
-
# => "World"
|
1540
|
-
```
|
51
|
+
*fatkodima*
|
1541
52
|
|
1542
|
-
|
1543
|
-
attributes:
|
53
|
+
* Fix `index_errors` having incorrect index in association validation errors.
|
1544
54
|
|
1545
|
-
|
1546
|
-
Post.encrypts :body
|
55
|
+
*lulalala*
|
1547
56
|
|
1548
|
-
|
1549
|
-
post.ciphertext_for(:body)
|
1550
|
-
# => "{\"p\":\"abc..."
|
57
|
+
* Add `index_errors: :nested_attributes_order` mode.
|
1551
58
|
|
1552
|
-
|
1553
|
-
post.ciphertext_for(:body)
|
1554
|
-
# => "{\"p\":\"xyz..."
|
1555
|
-
```
|
59
|
+
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.
|
1556
60
|
|
1557
|
-
*
|
61
|
+
*lulalala*
|
1558
62
|
|
1559
|
-
*
|
63
|
+
* Add `Rails.application.config.active_record.postgresql_adapter_decode_dates` to opt out of decoding dates automatically with the postgresql adapter. Defaults to true.
|
1560
64
|
|
1561
|
-
*
|
65
|
+
*Joé Dupuis*
|
1562
66
|
|
1563
|
-
*
|
67
|
+
* Association option `query_constraints` is deprecated in favor of `foreign_key`.
|
1564
68
|
|
1565
|
-
|
1566
|
-
be encrypted on create, but were not:
|
69
|
+
*Nikita Vasilevsky*
|
1567
70
|
|
1568
|
-
|
1569
|
-
Book.encrypts :name
|
71
|
+
* Add `ENV["SKIP_TEST_DATABASE_TRUNCATE"]` flag to speed up multi-process test runs on large DBs when all tests run within default transaction.
|
1570
72
|
|
1571
|
-
|
1572
|
-
book.name
|
1573
|
-
# => "<untitled>"
|
1574
|
-
book.name_before_type_cast
|
1575
|
-
# => "{\"p\":\"abc..."
|
1576
|
-
book.reload.name_before_type_cast
|
1577
|
-
# => "<untitled>"
|
1578
|
-
```
|
73
|
+
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.
|
1579
74
|
|
1580
|
-
|
75
|
+
*DHH*
|
1581
76
|
|
1582
|
-
|
1583
|
-
Book.encrypts :name
|
77
|
+
* Added support for recursive common table expressions.
|
1584
78
|
|
1585
|
-
|
1586
|
-
|
1587
|
-
|
1588
|
-
|
1589
|
-
|
1590
|
-
|
1591
|
-
|
1592
|
-
|
79
|
+
```ruby
|
80
|
+
Post.with_recursive(
|
81
|
+
post_and_replies: [
|
82
|
+
Post.where(id: 42),
|
83
|
+
Post.joins('JOIN post_and_replies ON posts.in_reply_to_id = post_and_replies.id'),
|
84
|
+
]
|
85
|
+
)
|
86
|
+
```
|
1593
87
|
|
1594
|
-
|
88
|
+
Generates the following SQL:
|
1595
89
|
|
1596
|
-
|
90
|
+
```sql
|
91
|
+
WITH RECURSIVE "post_and_replies" AS (
|
92
|
+
(SELECT "posts".* FROM "posts" WHERE "posts"."id" = 42)
|
93
|
+
UNION ALL
|
94
|
+
(SELECT "posts".* FROM "posts" JOIN post_and_replies ON posts.in_reply_to_id = post_and_replies.id)
|
95
|
+
)
|
96
|
+
SELECT "posts".* FROM "posts"
|
97
|
+
```
|
1597
98
|
|
1598
|
-
|
99
|
+
*ClearlyClaire*
|
1599
100
|
|
1600
|
-
|
101
|
+
* `validate_constraint` can be called in a `change_table` block.
|
1601
102
|
|
1602
|
-
|
103
|
+
ex:
|
104
|
+
```ruby
|
105
|
+
change_table :products do |t|
|
106
|
+
t.check_constraint "price > discounted_price", name: "price_check", validate: false
|
107
|
+
t.validate_check_constraint "price_check"
|
108
|
+
end
|
109
|
+
```
|
1603
110
|
|
1604
|
-
*
|
111
|
+
*Cody Cutrer*
|
1605
112
|
|
1606
|
-
*
|
113
|
+
* `PostgreSQLAdapter` now decodes columns of type date to `Date` instead of string.
|
1607
114
|
|
1608
|
-
|
1609
|
-
|
1610
|
-
|
115
|
+
Ex:
|
116
|
+
```ruby
|
117
|
+
ActiveRecord::Base.connection
|
118
|
+
.select_value("select '2024-01-01'::date").class #=> Date
|
119
|
+
```
|
1611
120
|
|
1612
|
-
*
|
121
|
+
*Joé Dupuis*
|
1613
122
|
|
1614
|
-
*
|
123
|
+
* Strict loading using `:n_plus_one_only` does not eagerly load child associations.
|
1615
124
|
|
1616
|
-
|
125
|
+
With this change, child associations are no longer eagerly loaded, to
|
126
|
+
match intended behavior and to prevent non-deterministic order issues caused
|
127
|
+
by calling methods like `first` or `last`. As `first` and `last` don't cause
|
128
|
+
an N+1 by themselves, calling child associations will no longer raise.
|
129
|
+
Fixes #49473.
|
1617
130
|
|
1618
|
-
|
131
|
+
Before:
|
1619
132
|
|
1620
|
-
|
133
|
+
```ruby
|
134
|
+
person = Person.find(1)
|
135
|
+
person.strict_loading!(mode: :n_plus_one_only)
|
136
|
+
person.posts.first
|
137
|
+
# SELECT * FROM posts WHERE person_id = 1; -- non-deterministic order
|
138
|
+
person.posts.first.firm # raises ActiveRecord::StrictLoadingViolationError
|
139
|
+
```
|
1621
140
|
|
1622
|
-
|
1623
|
-
configurations.
|
141
|
+
After:
|
1624
142
|
|
1625
|
-
|
143
|
+
```ruby
|
144
|
+
person = Person.find(1)
|
145
|
+
person.strict_loading!(mode: :n_plus_one_only)
|
146
|
+
person.posts.first # this is 1+1, not N+1
|
147
|
+
# SELECT * FROM posts WHERE person_id = 1 ORDER BY id LIMIT 1;
|
148
|
+
person.posts.first.firm # no longer raises
|
149
|
+
```
|
1626
150
|
|
1627
|
-
*
|
151
|
+
*Reid Lynch*
|
1628
152
|
|
1629
|
-
*
|
153
|
+
* Allow `Sqlite3Adapter` to use `sqlite3` gem version `2.x`.
|
1630
154
|
|
1631
|
-
|
1632
|
-
shows which table it concerns.
|
155
|
+
*Mike Dalessio*
|
1633
156
|
|
1634
|
-
|
157
|
+
* Allow `ActiveRecord::Base#pluck` to accept hash values.
|
1635
158
|
|
1636
|
-
|
159
|
+
```ruby
|
160
|
+
# Before
|
161
|
+
Post.joins(:comments).pluck("posts.id", "comments.id", "comments.body")
|
1637
162
|
|
1638
|
-
|
1639
|
-
|
1640
|
-
|
163
|
+
# After
|
164
|
+
Post.joins(:comments).pluck(posts: [:id], comments: [:id, :body])
|
165
|
+
```
|
1641
166
|
|
1642
|
-
|
1643
|
-
t.virtual :name, type: datetime, precision: nil, as: "expression"
|
167
|
+
*fatkodima*
|
1644
168
|
|
1645
|
-
|
1646
|
-
datetime column default precisions match.
|
169
|
+
* Raise an `ActiveRecord::ActiveRecordError` error when the MySQL database returns an invalid version string.
|
1647
170
|
|
1648
|
-
*
|
171
|
+
*Kevin McPhillips*
|
1649
172
|
|
1650
|
-
*
|
173
|
+
* `ActiveRecord::Base.transaction` now yields an `ActiveRecord::Transaction` object.
|
1651
174
|
|
1652
|
-
This
|
1653
|
-
that `#with_raw_connection` offers.
|
175
|
+
This allows to register callbacks on it.
|
1654
176
|
|
1655
|
-
|
177
|
+
```ruby
|
178
|
+
Article.transaction do |transaction|
|
179
|
+
article.update(published: true)
|
180
|
+
transaction.after_commit do
|
181
|
+
PublishNotificationMailer.with(article: article).deliver_later
|
182
|
+
end
|
183
|
+
end
|
184
|
+
```
|
1656
185
|
|
1657
|
-
*
|
186
|
+
*Jean Boussier*
|
1658
187
|
|
1659
|
-
|
188
|
+
* Add `ActiveRecord::Base.current_transaction`.
|
1660
189
|
|
1661
|
-
|
190
|
+
Returns the current transaction, to allow registering callbacks on it.
|
1662
191
|
|
1663
|
-
|
1664
|
-
|
1665
|
-
|
1666
|
-
|
1667
|
-
|
192
|
+
```ruby
|
193
|
+
Article.current_transaction.after_commit do
|
194
|
+
PublishNotificationMailer.with(article: article).deliver_later
|
195
|
+
end
|
196
|
+
```
|
1668
197
|
|
1669
|
-
*
|
198
|
+
*Jean Boussier*
|
1670
199
|
|
1671
|
-
*
|
200
|
+
* Add `ActiveRecord.after_all_transactions_commit` callback.
|
1672
201
|
|
1673
|
-
|
202
|
+
Useful for code that may run either inside or outside a transaction and needs
|
203
|
+
to perform work after the state changes have been properly persisted.
|
1674
204
|
|
1675
|
-
|
205
|
+
```ruby
|
206
|
+
def publish_article(article)
|
207
|
+
article.update(published: true)
|
208
|
+
ActiveRecord.after_all_transactions_commit do
|
209
|
+
PublishNotificationMailer.with(article: article).deliver_later
|
210
|
+
end
|
211
|
+
end
|
212
|
+
```
|
1676
213
|
|
1677
|
-
|
1678
|
-
|
1679
|
-
for MySQL database tasks like creating a database and dumping the structure.
|
214
|
+
In the above example, the block is either executed immediately if called outside
|
215
|
+
of a transaction, or called after the open transaction is committed.
|
1680
216
|
|
1681
|
-
|
217
|
+
If the transaction is rolled back, the block isn't called.
|
1682
218
|
|
1683
|
-
*
|
219
|
+
*Jean Boussier*
|
1684
220
|
|
1685
|
-
|
221
|
+
* Add the ability to ignore counter cache columns until they are backfilled.
|
1686
222
|
|
1687
|
-
|
223
|
+
Starting to use counter caches on existing large tables can be troublesome, because the column
|
224
|
+
values must be backfilled separately of the column addition (to not lock the table for too long)
|
225
|
+
and before the use of `:counter_cache` (otherwise methods like `size`/`any?`/etc, which use
|
226
|
+
counter caches internally, can produce incorrect results). People usually use database triggers
|
227
|
+
or callbacks on child associations while backfilling before introducing a counter cache
|
228
|
+
configuration to the association.
|
1688
229
|
|
1689
|
-
|
230
|
+
Now, to safely backfill the column, while keeping the column updated with child records added/removed, use:
|
1690
231
|
|
1691
|
-
|
1692
|
-
|
1693
|
-
|
1694
|
-
|
1695
|
-
```
|
1696
|
-
Record.where("duration = ?", 1.hour.to_i)
|
1697
|
-
```
|
1698
|
-
If you want to use a duration as an ISO 8601 string:
|
1699
|
-
```
|
1700
|
-
Record.where("duration = ?", 1.hour.iso8601)
|
232
|
+
```ruby
|
233
|
+
class Comment < ApplicationRecord
|
234
|
+
belongs_to :post, counter_cache: { active: false }
|
235
|
+
end
|
1701
236
|
```
|
1702
237
|
|
1703
|
-
|
238
|
+
While the counter cache is not "active", the methods like `size`/`any?`/etc will not use it,
|
239
|
+
but get the results directly from the database. After the counter cache column is backfilled, simply
|
240
|
+
remove the `{ active: false }` part from the counter cache definition, and it will now be used by the
|
241
|
+
mentioned methods.
|
1704
242
|
|
1705
|
-
*
|
243
|
+
*fatkodima*
|
1706
244
|
|
1707
|
-
|
1708
|
-
Post.in_order_of("id", [4,2,3,1]).to_a
|
1709
|
-
Post.joins(:author).in_order_of("authors.name", ["Bob", "Anna", "John"]).to_a
|
1710
|
-
```
|
245
|
+
* Retry known idempotent SELECT queries on connection-related exceptions.
|
1711
246
|
|
1712
|
-
|
247
|
+
SELECT queries we construct by walking the Arel tree and / or with known model attributes
|
248
|
+
are idempotent and can safely be retried in the case of a connection error. Previously,
|
249
|
+
adapters such as `TrilogyAdapter` would raise `ActiveRecord::ConnectionFailed: Trilogy::EOFError`
|
250
|
+
when encountering a connection error mid-request.
|
1713
251
|
|
1714
|
-
*
|
252
|
+
*Adrianna Chang*
|
1715
253
|
|
1716
|
-
|
254
|
+
* Allow association's `foreign_key` to be composite.
|
1717
255
|
|
1718
|
-
|
256
|
+
`query_constraints` option was the only way to configure a composite foreign key by passing an `Array`.
|
257
|
+
Now it's possible to pass an Array value as `foreign_key` to achieve the same behavior of an association.
|
1719
258
|
|
1720
|
-
*
|
259
|
+
*Nikita Vasilevsky*
|
1721
260
|
|
1722
|
-
|
261
|
+
* Allow association's `primary_key` to be composite.
|
1723
262
|
|
1724
|
-
|
263
|
+
Association's `primary_key` can be composite when derived from associated model `primary_key` or `query_constraints`.
|
264
|
+
Now it's possible to explicitly set it as composite on the association.
|
1725
265
|
|
1726
|
-
*
|
266
|
+
*Nikita Vasilevsky*
|
1727
267
|
|
1728
|
-
|
268
|
+
* Add `config.active_record.permanent_connection_checkout` setting.
|
1729
269
|
|
1730
|
-
|
270
|
+
Controls whether `ActiveRecord::Base.connection` raises an error, emits a deprecation warning, or neither.
|
1731
271
|
|
272
|
+
`ActiveRecord::Base.connection` checkouts a database connection from the pool and keeps it leased until the end of
|
273
|
+
the request or job. This behavior can be undesirable in environments that use many more threads or fibers than there
|
274
|
+
is available connections.
|
1732
275
|
|
1733
|
-
|
276
|
+
This configuration can be used to track down and eliminate code that calls `ActiveRecord::Base.connection` and
|
277
|
+
migrate it to use `ActiveRecord::Base.with_connection` instead.
|
1734
278
|
|
1735
|
-
|
279
|
+
The default behavior remains unchanged, and there is currently no plans to change the default.
|
1736
280
|
|
1737
|
-
|
281
|
+
*Jean Boussier*
|
1738
282
|
|
1739
|
-
|
1740
|
-
Post.joins(:comments).select(posts: [:id, :title, :created_at], comments: [:id, :body, :author_id])
|
1741
|
-
#=> "SELECT \"posts\".\"id\", \"posts\".\"title\", \"posts\".\"created_at\", \"comments\".\"id\", \"comments\".\"body\", \"comments\".\"author_id\"
|
1742
|
-
# FROM \"posts\" INNER JOIN \"comments\" ON \"comments\".\"post_id\" = \"posts\".\"id\""
|
283
|
+
* Add dirties option to uncached.
|
1743
284
|
|
1744
|
-
|
1745
|
-
|
1746
|
-
# FROM \"posts\" INNER JOIN \"comments\" ON \"comments\".\"post_id\" = \"posts\".\"id\""
|
1747
|
-
```
|
1748
|
-
*Oleksandr Holubenko*, *Josef Šimánek*, *Jean Boussier*
|
285
|
+
This adds a `dirties` option to `ActiveRecord::Base.uncached` and
|
286
|
+
`ActiveRecord::ConnectionAdapters::ConnectionPool#uncached`.
|
1749
287
|
|
1750
|
-
|
288
|
+
When set to `true` (the default), writes will clear all query caches belonging to the current thread.
|
289
|
+
When set to `false`, writes to the affected connection pool will not clear any query cache.
|
1751
290
|
|
1752
|
-
|
1753
|
-
attributes such that the extra attributes from target are added.
|
291
|
+
This is needed by Solid Cache so that cache writes do not clear query caches.
|
1754
292
|
|
1755
|
-
|
1756
|
-
class Person < ApplicationRecord
|
1757
|
-
end
|
293
|
+
*Donal McBreen*
|
1758
294
|
|
1759
|
-
|
1760
|
-
attribute :is_admin, :boolean
|
1761
|
-
after_initialize :set_admin
|
295
|
+
* Deprecate `ActiveRecord::Base.connection` in favor of `.lease_connection`.
|
1762
296
|
|
1763
|
-
|
1764
|
-
|
1765
|
-
end
|
1766
|
-
end
|
297
|
+
The method has been renamed as `lease_connection` to better reflect that the returned
|
298
|
+
connection will be held for the duration of the request or job.
|
1767
299
|
|
1768
|
-
|
1769
|
-
|
1770
|
-
# => false
|
1771
|
-
person.becomes(WebUser).is_admin?
|
1772
|
-
# => true
|
1773
|
-
```
|
300
|
+
This deprecation is a soft deprecation, no warnings will be issued and there is no
|
301
|
+
current plan to remove the method.
|
1774
302
|
|
1775
|
-
*
|
303
|
+
*Jean Boussier*
|
1776
304
|
|
1777
|
-
*
|
1778
|
-
behavior of `Enumerable#in_order_of`.
|
305
|
+
* Deprecate `ActiveRecord::ConnectionAdapters::ConnectionPool#connection`.
|
1779
306
|
|
1780
|
-
|
1781
|
-
|
307
|
+
The method has been renamed as `lease_connection` to better reflect that the returned
|
308
|
+
connection will be held for the duration of the request or job.
|
1782
309
|
|
1783
|
-
*
|
310
|
+
*Jean Boussier*
|
1784
311
|
|
1785
|
-
*
|
312
|
+
* Expose a generic fixture accessor for fixture names that may conflict with Minitest.
|
1786
313
|
|
1787
314
|
```ruby
|
1788
|
-
|
1789
|
-
|
1790
|
-
|
1791
|
-
Now results in the following SQL:
|
1792
|
-
|
1793
|
-
```sql
|
1794
|
-
ALTER TABLE "my_table" ADD COLUMN "created_at" datetime(6) NOT NULL, ADD COLUMN "updated_at" datetime(6) NOT NULL
|
315
|
+
assert_equal "Ruby on Rails", web_sites(:rubyonrails).name
|
316
|
+
assert_equal "Ruby on Rails", fixture(:web_sites, :rubyonrails).name
|
1795
317
|
```
|
1796
318
|
|
1797
|
-
*
|
319
|
+
*Jean Boussier*
|
1798
320
|
|
1799
|
-
*
|
321
|
+
* Using `Model.query_constraints` with a single non-primary-key column used to raise as expected, but with an
|
322
|
+
incorrect error message.
|
1800
323
|
|
1801
|
-
This
|
1802
|
-
dropped columns that depend on it.
|
324
|
+
This has been fixed to raise with a more appropriate error message.
|
1803
325
|
|
1804
|
-
*
|
326
|
+
*Joshua Young*
|
1805
327
|
|
1806
|
-
*
|
328
|
+
* Fix `has_one` association autosave setting the foreign key attribute when it is unchanged.
|
1807
329
|
|
1808
|
-
|
1809
|
-
|
330
|
+
This behavior is also inconsistent with autosaving `belongs_to` and can have unintended side effects like raising
|
331
|
+
an `ActiveRecord::ReadonlyAttributeError` when the foreign key attribute is marked as read-only.
|
1810
332
|
|
1811
|
-
*
|
333
|
+
*Joshua Young*
|
1812
334
|
|
1813
|
-
*
|
335
|
+
* Remove deprecated behavior that would rollback a transaction block when exited using `return`, `break` or `throw`.
|
1814
336
|
|
1815
|
-
|
1816
|
-
duplicate records or failing with `ActiveRecord::RecordNotUnique` depending on
|
1817
|
-
whether a proper unicity constraint was set.
|
337
|
+
*Rafael Mendonça França*
|
1818
338
|
|
1819
|
-
|
1820
|
-
when the record is expected to exist most of the time, as INSERT require to send
|
1821
|
-
more data than SELECT and require more work from the database. Also on some
|
1822
|
-
databases it can actually consume a primary key increment which is undesirable.
|
339
|
+
* Deprecate `Rails.application.config.active_record.commit_transaction_on_non_local_return`.
|
1823
340
|
|
1824
|
-
|
1825
|
-
can be made race-condition free by re-trying the `find` if the `create` failed
|
1826
|
-
with `ActiveRecord::RecordNotUnique`. This assumes that the table has the proper
|
1827
|
-
unicity constraints, if not, `find_or_create_by` will still lead to duplicated records.
|
341
|
+
*Rafael Mendonça França*
|
1828
342
|
|
1829
|
-
|
343
|
+
* Remove deprecated support to pass `rewhere` to `ActiveRecord::Relation#merge`.
|
1830
344
|
|
1831
|
-
*
|
345
|
+
*Rafael Mendonça França*
|
1832
346
|
|
1833
|
-
|
1834
|
-
support reconnect, but also expected to be passed an initial already-
|
1835
|
-
established connection.
|
347
|
+
* Remove deprecated support to pass `deferrable: true` to `add_foreign_key`.
|
1836
348
|
|
1837
|
-
|
1838
|
-
config hash, and only establish the real connection on demand.
|
349
|
+
*Rafael Mendonça França*
|
1839
350
|
|
1840
|
-
|
351
|
+
* Remove deprecated support to quote `ActiveSupport::Duration`.
|
1841
352
|
|
1842
|
-
*
|
1843
|
-
checkout when possible.
|
353
|
+
*Rafael Mendonça França*
|
1844
354
|
|
1845
|
-
|
1846
|
-
used directly to validate the connection, saving a network round-trip.
|
355
|
+
* Remove deprecated `#quote_bound_value`.
|
1847
356
|
|
1848
|
-
*
|
357
|
+
*Rafael Mendonça França*
|
1849
358
|
|
1850
|
-
*
|
1851
|
-
mid-request.
|
359
|
+
* Remove deprecated `ActiveRecord::ConnectionAdapters::ConnectionPool#connection_klass`.
|
1852
360
|
|
1853
|
-
|
1854
|
-
not inside a transaction, it is safe to immediately reconnect to the
|
1855
|
-
database server and try again, so this is now the default behavior.
|
361
|
+
*Rafael Mendonça França*
|
1856
362
|
|
1857
|
-
|
1858
|
-
|
1859
|
-
|
1860
|
-
option to `0`.
|
363
|
+
* Remove deprecated support to apply `#connection_pool_list`, `#active_connections?`, `#clear_active_connections!`,
|
364
|
+
`#clear_reloadable_connections!`, `#clear_all_connections!` and `#flush_idle_connections!` to the connections pools
|
365
|
+
for the current role when the `role` argument isn't provided.
|
1861
366
|
|
1862
|
-
*
|
367
|
+
*Rafael Mendonça França*
|
1863
368
|
|
1864
|
-
*
|
369
|
+
* Remove deprecated `#all_connection_pools`.
|
1865
370
|
|
1866
|
-
|
371
|
+
*Rafael Mendonça França*
|
1867
372
|
|
1868
|
-
|
373
|
+
* Remove deprecated `ActiveRecord::ConnectionAdapters::SchemaCache#data_sources`.
|
1869
374
|
|
1870
|
-
|
1871
|
-
disable_extension :citext, force: :cascade
|
1872
|
-
```
|
375
|
+
*Rafael Mendonça França*
|
1873
376
|
|
1874
|
-
|
377
|
+
* Remove deprecated `ActiveRecord::ConnectionAdapters::SchemaCache.load_from`.
|
1875
378
|
|
1876
|
-
*
|
379
|
+
*Rafael Mendonça França*
|
1877
380
|
|
1878
|
-
*
|
381
|
+
* Remove deprecated `#all_foreign_keys_valid?` from database adapters.
|
1879
382
|
|
1880
|
-
*
|
383
|
+
*Rafael Mendonça França*
|
1881
384
|
|
1882
|
-
*
|
385
|
+
* Remove deprecated support to passing coder and class as second argument to `serialize`.
|
1883
386
|
|
1884
|
-
|
1885
|
-
and moves the configuration of `ActiveRecord::DestroyAssociationAsyncJob`
|
1886
|
-
from ActiveJob to ActiveRecord.
|
387
|
+
*Rafael Mendonça França*
|
1887
388
|
|
1888
|
-
|
1889
|
-
if the job class is unloadable or an `ActiveRecord::ConfigurationError` if
|
1890
|
-
`dependent: :destroy_async` is declared on an association but there is no job
|
1891
|
-
class configured.
|
389
|
+
* Remove deprecated support to `ActiveRecord::Base#read_attribute(:id)` to return the custom primary key value.
|
1892
390
|
|
1893
|
-
*
|
391
|
+
*Rafael Mendonça França*
|
1894
392
|
|
1895
|
-
*
|
393
|
+
* Remove deprecated `TestFixtures.fixture_path`.
|
1896
394
|
|
1897
|
-
|
1898
|
-
which is wasteful and cause problem with YAML safe_load.
|
395
|
+
*Rafael Mendonça França*
|
1899
396
|
|
1900
|
-
|
397
|
+
* Remove deprecated behavior to support referring to a singular association by its plural name.
|
1901
398
|
|
1902
|
-
*
|
399
|
+
*Rafael Mendonça França*
|
1903
400
|
|
1904
|
-
|
401
|
+
* Deprecate `Rails.application.config.active_record.allow_deprecated_singular_associations_name`.
|
1905
402
|
|
1906
|
-
|
403
|
+
*Rafael Mendonça França*
|
1907
404
|
|
1908
|
-
|
1909
|
-
ActiveRecord::
|
1910
|
-
```
|
405
|
+
* Remove deprecated support to passing `SchemaMigration` and `InternalMetadata` classes as arguments to
|
406
|
+
`ActiveRecord::MigrationContext`.
|
1911
407
|
|
1912
|
-
*
|
408
|
+
*Rafael Mendonça França*
|
1913
409
|
|
1914
|
-
*
|
410
|
+
* Remove deprecated `ActiveRecord::Migration.check_pending` method.
|
1915
411
|
|
1916
|
-
|
1917
|
-
resetting a password. However, signed IDs cannot reflect record state, so
|
1918
|
-
if a token is intended to be single-use, it must be tracked in a database at
|
1919
|
-
least until it expires.
|
412
|
+
*Rafael Mendonça França*
|
1920
413
|
|
1921
|
-
|
1922
|
-
using the token to fetch the record, the data from the token and the current
|
1923
|
-
data from the record will be compared. If the two do not match, the token
|
1924
|
-
will be treated as invalid, the same as if it had expired. For example:
|
414
|
+
* Remove deprecated `ActiveRecord::LogSubscriber.runtime` method.
|
1925
415
|
|
1926
|
-
|
1927
|
-
class User < ActiveRecord::Base
|
1928
|
-
has_secure_password
|
1929
|
-
|
1930
|
-
generates_token_for :password_reset, expires_in: 15.minutes do
|
1931
|
-
# A password's BCrypt salt changes when the password is updated.
|
1932
|
-
# By embedding (part of) the salt in a token, the token will
|
1933
|
-
# expire when the password is updated.
|
1934
|
-
BCrypt::Password.new(password_digest).salt[-10..]
|
1935
|
-
end
|
1936
|
-
end
|
416
|
+
*Rafael Mendonça França*
|
1937
417
|
|
1938
|
-
|
1939
|
-
token = user.generate_token_for(:password_reset)
|
418
|
+
* Remove deprecated `ActiveRecord::LogSubscriber.runtime=` method.
|
1940
419
|
|
1941
|
-
|
420
|
+
*Rafael Mendonça França*
|
1942
421
|
|
1943
|
-
|
1944
|
-
User.find_by_token_for(:password_reset, token) # => nil
|
1945
|
-
```
|
422
|
+
* Remove deprecated `ActiveRecord::LogSubscriber.reset_runtime` method.
|
1946
423
|
|
1947
|
-
*
|
424
|
+
*Rafael Mendonça França*
|
1948
425
|
|
1949
|
-
*
|
426
|
+
* Remove deprecated support to define `explain` in the connection adapter with 2 arguments.
|
1950
427
|
|
1951
|
-
|
1952
|
-
When iterating over the whole tables, this approach is not optimal as it loads unneeded ids and
|
1953
|
-
`IN` queries with lots of items are slow.
|
428
|
+
*Rafael Mendonça França*
|
1954
429
|
|
1955
|
-
|
1956
|
-
several times faster. E.g., tested on a PostgreSQL table with 10 million records: querying (`253s` vs `30s`),
|
1957
|
-
updating (`288s` vs `124s`), deleting (`268s` vs `83s`).
|
430
|
+
* Remove deprecated `ActiveRecord::ActiveJobRequiredError`.
|
1958
431
|
|
1959
|
-
|
1960
|
-
If you iterate over the table and the only condition is, e.g., `archived_at: nil` (and only a tiny fraction
|
1961
|
-
of the records are archived), it makes sense to opt in to this approach:
|
432
|
+
*Rafael Mendonça França*
|
1962
433
|
|
1963
|
-
|
1964
|
-
Project.where(archived_at: nil).in_batches(use_ranges: true) do |relation|
|
1965
|
-
# do something
|
1966
|
-
end
|
1967
|
-
```
|
434
|
+
* Remove deprecated `ActiveRecord::Base.clear_active_connections!`.
|
1968
435
|
|
1969
|
-
|
436
|
+
*Rafael Mendonça França*
|
1970
437
|
|
1971
|
-
|
438
|
+
* Remove deprecated `ActiveRecord::Base.clear_reloadable_connections!`.
|
1972
439
|
|
1973
|
-
*
|
440
|
+
*Rafael Mendonça França*
|
1974
441
|
|
1975
|
-
|
1976
|
-
Post.with(posts_with_comments: Post.where("comments_count > ?", 0))
|
1977
|
-
# => ActiveRecord::Relation
|
1978
|
-
# WITH posts_with_comments AS (SELECT * FROM posts WHERE (comments_count > 0)) SELECT * FROM posts
|
1979
|
-
```
|
442
|
+
* Remove deprecated `ActiveRecord::Base.clear_all_connections!`.
|
1980
443
|
|
1981
|
-
*
|
444
|
+
*Rafael Mendonça França*
|
1982
445
|
|
1983
|
-
*
|
446
|
+
* Remove deprecated `ActiveRecord::Base.flush_idle_connections!`.
|
1984
447
|
|
1985
|
-
|
448
|
+
*Rafael Mendonça França*
|
1986
449
|
|
1987
|
-
|
450
|
+
* Remove deprecated `name` argument from `ActiveRecord::Base.remove_connection`.
|
1988
451
|
|
1989
|
-
*
|
452
|
+
*Rafael Mendonça França*
|
1990
453
|
|
1991
|
-
*
|
454
|
+
* Remove deprecated support to call `alias_attribute` with non-existent attribute names.
|
1992
455
|
|
1993
|
-
*
|
456
|
+
*Rafael Mendonça França*
|
1994
457
|
|
1995
|
-
*
|
458
|
+
* Remove deprecated `Rails.application.config.active_record.suppress_multiple_database_warning`.
|
1996
459
|
|
1997
|
-
|
1998
|
-
# In database migrations
|
1999
|
-
add_column :shops, :open_hours, :tsrange, array: true
|
2000
|
-
# In app config
|
2001
|
-
ActiveRecord::Base.time_zone_aware_types += [:tsrange]
|
2002
|
-
# In the code times are properly converted to app time zone
|
2003
|
-
Shop.create!(open_hours: [Time.current..8.hour.from_now])
|
2004
|
-
```
|
460
|
+
*Rafael Mendonça França*
|
2005
461
|
|
2006
|
-
|
462
|
+
* Add `ActiveRecord::Encryption::MessagePackMessageSerializer`.
|
2007
463
|
|
2008
|
-
|
464
|
+
Serialize data to the MessagePack format, for efficient storage in binary columns.
|
2009
465
|
|
2010
|
-
|
2011
|
-
|
2012
|
-
to change how their migrations run.
|
466
|
+
The binary encoding requires around 30% less space than the base64 encoding
|
467
|
+
used by the default serializer.
|
2013
468
|
|
2014
|
-
*
|
469
|
+
*Donal McBreen*
|
2015
470
|
|
2016
|
-
* Add
|
471
|
+
* Add support for encrypting binary columns.
|
2017
472
|
|
2018
|
-
|
2019
|
-
foreign key constraints usage even if the underlying database supports them.
|
473
|
+
Ensure encryption and decryption pass `Type::Binary::Data` around for binary data.
|
2020
474
|
|
2021
|
-
|
2022
|
-
|
2023
|
-
development:
|
2024
|
-
<<: *default
|
2025
|
-
database: storage/development.sqlite3
|
2026
|
-
foreign_keys: false
|
2027
|
-
```
|
475
|
+
Previously encrypting binary columns with the `ActiveRecord::Encryption::MessageSerializer`
|
476
|
+
incidentally worked for MySQL and SQLite, but not PostgreSQL.
|
2028
477
|
|
2029
|
-
*
|
478
|
+
*Donal McBreen*
|
2030
479
|
|
2031
|
-
*
|
480
|
+
* Deprecated `ENV["SCHEMA_CACHE"]` in favor of `schema_cache_path` in the database configuration.
|
2032
481
|
|
2033
|
-
|
2034
|
-
It is possible to opt into the new more performant behavior with `config.active_record.allow_deprecated_singular_associations_name = false`
|
482
|
+
*Rafael Mendonça França*
|
2035
483
|
|
2036
|
-
|
484
|
+
* Add `ActiveRecord::Base.with_connection` as a shortcut for leasing a connection for a short duration.
|
2037
485
|
|
2038
|
-
|
2039
|
-
|
486
|
+
The leased connection is yielded, and for the duration of the block, any call to `ActiveRecord::Base.connection`
|
487
|
+
will yield that same connection.
|
2040
488
|
|
2041
|
-
|
2042
|
-
|
2043
|
-
only one of them. `config.active_record.run_commit_callbacks_on_first_saved_instances_in_transaction`
|
2044
|
-
was added to specify how Rails chooses which instance receives the
|
2045
|
-
callbacks. The framework defaults were changed to use the new logic.
|
489
|
+
This is useful to perform a few database operations without causing a connection to be leased for the
|
490
|
+
entire duration of the request or job.
|
2046
491
|
|
2047
|
-
|
2048
|
-
is `true`, transactional callbacks are run on the first instance to save,
|
2049
|
-
even though its instance state may be stale.
|
492
|
+
*Jean Boussier*
|
2050
493
|
|
2051
|
-
|
2052
|
-
|
2053
|
-
instance state. Those instances are chosen as follows:
|
494
|
+
* Deprecate `config.active_record.warn_on_records_fetched_greater_than` now that `sql.active_record`
|
495
|
+
notification includes `:row_count` field.
|
2054
496
|
|
2055
|
-
|
2056
|
-
given record within the transaction.
|
2057
|
-
- There are two exceptions:
|
2058
|
-
- If the record is created within the transaction, then updated by
|
2059
|
-
another instance, `after_create_commit` callbacks will be run on the
|
2060
|
-
second instance. This is instead of the `after_update_commit`
|
2061
|
-
callbacks that would naively be run based on that instance’s state.
|
2062
|
-
- If the record is destroyed within the transaction, then
|
2063
|
-
`after_destroy_commit` callbacks will be fired on the last destroyed
|
2064
|
-
instance, even if a stale instance subsequently performed an update
|
2065
|
-
(which will have affected 0 rows).
|
497
|
+
*Jason Nochlin*
|
2066
498
|
|
2067
|
-
|
499
|
+
* The fix ensures that the association is joined using the appropriate join type
|
500
|
+
(either inner join or left outer join) based on the existing joins in the scope.
|
2068
501
|
|
2069
|
-
|
502
|
+
This prevents unintentional overrides of existing join types and ensures consistency in the generated SQL queries.
|
2070
503
|
|
2071
|
-
|
504
|
+
Example:
|
2072
505
|
|
2073
|
-
SQLite has some quirks around double-quoted string literals.
|
2074
|
-
It first tries to consider double-quoted strings as identifier names, but if they don't exist
|
2075
|
-
it then considers them as string literals. Because of this, typos can silently go unnoticed.
|
2076
|
-
For example, it is possible to create an index for a non existing column.
|
2077
|
-
See [SQLite documentation](https://www.sqlite.org/quirks.html#double_quoted_string_literals_are_accepted) for more details.
|
2078
506
|
|
2079
|
-
If you don't want this behavior, you can disable it via:
|
2080
507
|
|
2081
508
|
```ruby
|
2082
|
-
#
|
2083
|
-
|
509
|
+
# `associated` will use `LEFT JOIN` instead of using `JOIN`
|
510
|
+
Post.left_joins(:author).where.associated(:author)
|
2084
511
|
```
|
2085
512
|
|
2086
|
-
|
2087
|
-
|
2088
|
-
*fatkodima*, *Jean Boussier*
|
513
|
+
*Saleh Alhaddad*
|
2089
514
|
|
2090
|
-
*
|
515
|
+
* Fix an issue where `ActiveRecord::Encryption` configurations are not ready before the loading
|
516
|
+
of Active Record models, when an application is eager loaded. As a result, encrypted attributes
|
517
|
+
could be misconfigured in some cases.
|
2091
518
|
|
2092
|
-
|
2093
|
-
ivar. This led to a confusing situation where despite having the correct data the relation
|
2094
|
-
still reported a stale cache_version.
|
519
|
+
*Maxime Réty*
|
2095
520
|
|
2096
|
-
|
521
|
+
* Deprecate defining an `enum` with keyword arguments.
|
2097
522
|
|
2098
523
|
```ruby
|
2099
|
-
|
2100
|
-
|
2101
|
-
|
2102
|
-
|
524
|
+
class Function > ApplicationRecord
|
525
|
+
# BAD
|
526
|
+
enum color: [:red, :blue],
|
527
|
+
type: [:instance, :class]
|
2103
528
|
|
2104
|
-
|
2105
|
-
|
2106
|
-
|
529
|
+
# GOOD
|
530
|
+
enum :color, [:red, :blue]
|
531
|
+
enum :type, [:instance, :class]
|
532
|
+
end
|
2107
533
|
```
|
2108
534
|
|
2109
|
-
|
535
|
+
*Hartley McGuire*
|
536
|
+
|
537
|
+
* Add `config.active_record.validate_migration_timestamps` option for validating migration timestamps.
|
2110
538
|
|
2111
|
-
|
539
|
+
When set, validates that the timestamp prefix for a migration is no more than a day ahead of
|
540
|
+
the timestamp associated with the current time. This is designed to prevent migrations prefixes
|
541
|
+
from being hand-edited to future timestamps, which impacts migration generation and other
|
542
|
+
migration commands.
|
2112
543
|
|
2113
|
-
*
|
544
|
+
*Adrianna Chang*
|
2114
545
|
|
2115
|
-
|
2116
|
-
add_exclusion_constraint :invoices, "daterange(start_date, end_date) WITH &&", using: :gist, name: "invoices_date_overlap"
|
2117
|
-
remove_exclusion_constraint :invoices, name: "invoices_date_overlap"
|
2118
|
-
```
|
546
|
+
* Properly synchronize `Mysql2Adapter#active?` and `TrilogyAdapter#active?`.
|
2119
547
|
|
2120
|
-
|
548
|
+
As well as `disconnect!` and `verify!`.
|
2121
549
|
|
2122
|
-
|
550
|
+
This generally isn't a big problem as connections must not be shared between
|
551
|
+
threads, but is required when running transactional tests or system tests
|
552
|
+
and could lead to a SEGV.
|
2123
553
|
|
2124
|
-
*
|
554
|
+
*Jean Boussier*
|
2125
555
|
|
2126
|
-
|
2127
|
-
treat it as truthy and make your column nullable. This could be surprising, so now
|
2128
|
-
the input must be either `true` or `false`.
|
556
|
+
* Support `:source_location` tag option for query log tags.
|
2129
557
|
|
2130
558
|
```ruby
|
2131
|
-
|
2132
|
-
change_column_null :table, :column, false # good
|
2133
|
-
change_column_null :table, :column, from: true, to: false # raises (previously this made the column nullable)
|
559
|
+
config.active_record.query_log_tags << :source_location
|
2134
560
|
```
|
2135
561
|
|
2136
|
-
|
2137
|
-
|
2138
|
-
|
2139
|
-
|
2140
|
-
Fixes #45130.
|
562
|
+
Calculating the caller location is a costly operation and should be used primarily in development
|
563
|
+
(note, there is also a `config.active_record.verbose_query_logs` that serves the same purpose)
|
564
|
+
or occasionally on production for debugging purposes.
|
2141
565
|
|
2142
566
|
*fatkodima*
|
2143
567
|
|
2144
|
-
*
|
2145
|
-
|
2146
|
-
*Eddie Lebow*
|
568
|
+
* Add an option to `ActiveRecord::Encryption::Encryptor` to disable compression.
|
2147
569
|
|
2148
|
-
|
2149
|
-
|
2150
|
-
*edsharp*
|
2151
|
-
|
2152
|
-
* Add validity for PostgreSQL indexes.
|
570
|
+
Allow compression to be disabled by setting `compress: false`
|
2153
571
|
|
2154
572
|
```ruby
|
2155
|
-
|
2156
|
-
|
573
|
+
class User
|
574
|
+
encrypts :name, encryptor: ActiveRecord::Encryption::Encryptor.new(compress: false)
|
575
|
+
end
|
2157
576
|
```
|
2158
577
|
|
2159
|
-
*
|
578
|
+
*Donal McBreen*
|
2160
579
|
|
2161
|
-
*
|
580
|
+
* Deprecate passing strings to `ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename`.
|
2162
581
|
|
2163
|
-
|
582
|
+
A `ActiveRecord::DatabaseConfigurations::DatabaseConfig` object should be passed instead.
|
2164
583
|
|
2165
|
-
*
|
584
|
+
*Rafael Mendonça França*
|
2166
585
|
|
2167
|
-
|
2168
|
-
uniqueness of each attribute having a `uniqueness` validation, even if that attribute hasn't changed.
|
2169
|
-
If the database has the corresponding unique index, then this validation can never fail for persisted
|
2170
|
-
records, and we could safely skip it.
|
586
|
+
* Add `row_count` field to `sql.active_record` notification.
|
2171
587
|
|
2172
|
-
|
588
|
+
This field returns the amount of rows returned by the query that emitted the notification.
|
2173
589
|
|
2174
|
-
|
590
|
+
This metric is useful in cases where one wants to detect queries with big result sets.
|
2175
591
|
|
2176
|
-
|
592
|
+
*Marvin Bitterlich*
|
2177
593
|
|
2178
|
-
|
594
|
+
* Consistently raise an `ArgumentError` when passing an invalid argument to a nested attributes association writer.
|
2179
595
|
|
2180
|
-
|
596
|
+
Previously, this would only raise on collection associations and produce a generic error on singular associations.
|
2181
597
|
|
2182
|
-
|
598
|
+
Now, it will raise on both collection and singular associations.
|
2183
599
|
|
2184
|
-
*
|
600
|
+
*Joshua Young*
|
2185
601
|
|
2186
|
-
|
2187
|
-
ActiveRecord::SchemaDumper.ignore_tables = [/^_/]
|
2188
|
-
```
|
602
|
+
* Fix single quote escapes on default generated MySQL columns.
|
2189
603
|
|
2190
|
-
|
604
|
+
MySQL 5.7.5+ supports generated columns, which can be used to create a column that is computed from an expression.
|
2191
605
|
|
2192
|
-
|
606
|
+
Previously, the schema dump would output a string with double escapes for generated columns with single quotes in the default expression.
|
2193
607
|
|
2194
|
-
|
2195
|
-
contradiction, such as `User.where(id: []).count`. We no longer perform a
|
2196
|
-
query in that scenario.
|
608
|
+
This would result in issues when importing the schema on a fresh instance of a MySQL database.
|
2197
609
|
|
2198
|
-
|
2199
|
-
`minimum` and `maximum`
|
610
|
+
Now, the string will not be escaped and will be valid Ruby upon importing of the schema.
|
2200
611
|
|
2201
|
-
*
|
612
|
+
*Yash Kapadia*
|
2202
613
|
|
2203
|
-
*
|
614
|
+
* Fix Migrations with versions older than 7.1 validating options given to
|
615
|
+
`add_reference` and `t.references`.
|
2204
616
|
|
2205
|
-
|
2206
|
-
class Book < ApplicationRecord
|
2207
|
-
alias_attribute :title, :name
|
2208
|
-
end
|
617
|
+
*Hartley McGuire*
|
2209
618
|
|
2210
|
-
|
2211
|
-
```
|
619
|
+
* Add `<role>_types` class method to `ActiveRecord::DelegatedType` so that the delegated types can be introspected.
|
2212
620
|
|
2213
|
-
*
|
621
|
+
*JP Rosevear*
|
2214
622
|
|
2215
|
-
*
|
623
|
+
* Make `schema_dump`, `query_cache`, `replica` and `database_tasks` configurable via `DATABASE_URL`.
|
2216
624
|
|
2217
|
-
This
|
2218
|
-
It will encrypt those values at creation time. Before, it would raise an
|
2219
|
-
error unless `config.active_record.encryption.support_unencrypted_data` was true.
|
625
|
+
This wouldn't always work previously because boolean values would be interpreted as strings.
|
2220
626
|
|
2221
|
-
|
627
|
+
e.g. `DATABASE_URL=postgres://localhost/foo?schema_dump=false` now properly disable dumping the schema
|
628
|
+
cache.
|
2222
629
|
|
2223
|
-
*
|
630
|
+
*Mike Coutermarsh*, *Jean Boussier*
|
2224
631
|
|
2225
|
-
|
2226
|
-
but you can now change it to anything you like. If the method returns true,
|
2227
|
-
`Resolver#read` gets called meaning the request could be served by the
|
2228
|
-
replica database.
|
632
|
+
* Introduce `ActiveRecord::Transactions::ClassMethods#set_callback`.
|
2229
633
|
|
2230
|
-
|
634
|
+
It is identical to `ActiveSupport::Callbacks::ClassMethods#set_callback`
|
635
|
+
but with support for `after_commit` and `after_rollback` callback options.
|
2231
636
|
|
2232
|
-
*
|
637
|
+
*Joshua Young*
|
2233
638
|
|
2234
|
-
|
639
|
+
* Make `ActiveRecord::Encryption::Encryptor` agnostic of the serialization format used for encrypted data.
|
2235
640
|
|
2236
|
-
|
641
|
+
Previously, the encryptor instance only allowed an encrypted value serialized as a `String` to be passed to the message serializer.
|
2237
642
|
|
2238
|
-
|
2239
|
-
way to dump a schema to both SQL and Ruby formats. You can now do this with
|
2240
|
-
an environment variable. For example:
|
643
|
+
Now, the encryptor lets the configured `message_serializer` decide which types of serialized encrypted values are supported. A custom serialiser is therefore allowed to serialize `ActiveRecord::Encryption::Message` objects using a type other than `String`.
|
2241
644
|
|
2242
|
-
|
2243
|
-
SCHEMA_FORMAT=sql rake db:schema:dump
|
2244
|
-
```
|
645
|
+
The default `ActiveRecord::Encryption::MessageSerializer` already ensures that only `String` objects are passed for deserialization.
|
2245
646
|
|
2246
|
-
*
|
647
|
+
*Maxime Réty*
|
2247
648
|
|
2248
|
-
*
|
649
|
+
* Fix `encrypted_attribute?` to take into account context properties passed to `encrypts`.
|
2249
650
|
|
2250
|
-
|
2251
|
-
if using `db:schema:load`. Further more the function name would be
|
2252
|
-
added as string content when saving new records.
|
651
|
+
*Maxime Réty*
|
2253
652
|
|
2254
|
-
|
653
|
+
* The object returned by `explain` now responds to `pluck`, `first`,
|
654
|
+
`last`, `average`, `count`, `maximum`, `minimum`, and `sum`. Those
|
655
|
+
new methods run `EXPLAIN` on the corresponding queries:
|
2255
656
|
|
2256
|
-
|
657
|
+
```ruby
|
658
|
+
User.all.explain.count
|
659
|
+
# EXPLAIN SELECT COUNT(*) FROM `users`
|
660
|
+
# ...
|
2257
661
|
|
2258
|
-
|
2259
|
-
|
2260
|
-
|
2261
|
-
|
2262
|
-
in a single background job. If the number of dependent records is greater
|
2263
|
-
than this configuration, the records will be destroyed in multiple
|
2264
|
-
background jobs.
|
662
|
+
User.all.explain.maximum(:id)
|
663
|
+
# EXPLAIN SELECT MAX(`users`.`id`) FROM `users`
|
664
|
+
# ...
|
665
|
+
```
|
2265
666
|
|
2266
|
-
*
|
667
|
+
*Petrik de Heus*
|
2267
668
|
|
2268
|
-
*
|
669
|
+
* Fixes an issue where `validates_associated` `:on` option wasn't respected
|
670
|
+
when validating associated records.
|
2269
671
|
|
2270
|
-
*
|
672
|
+
*Austen Madden*, *Alex Ghiculescu*, *Rafał Brize*
|
2271
673
|
|
2272
|
-
*
|
674
|
+
* Allow overriding SQLite defaults from `database.yml`.
|
2273
675
|
|
2274
|
-
|
2275
|
-
|
676
|
+
Any PRAGMA configuration set under the `pragmas` key in the configuration
|
677
|
+
file takes precedence over Rails' defaults, and additional PRAGMAs can be
|
678
|
+
set as well.
|
2276
679
|
|
2277
|
-
```
|
2278
|
-
|
680
|
+
```yaml
|
681
|
+
database: storage/development.sqlite3
|
682
|
+
timeout: 5000
|
683
|
+
pragmas:
|
684
|
+
journal_mode: off
|
685
|
+
temp_store: memory
|
2279
686
|
```
|
2280
687
|
|
2281
|
-
*
|
2282
|
-
|
2283
|
-
* Reduce the memory footprint of fixtures accessors.
|
2284
|
-
|
2285
|
-
Until now fixtures accessors were eagerly defined using `define_method`.
|
2286
|
-
So the memory usage was directly dependent of the number of fixtures and
|
2287
|
-
test suites.
|
2288
|
-
|
2289
|
-
Instead fixtures accessors are now implemented with `method_missing`,
|
2290
|
-
so they incur much less memory and CPU overhead.
|
688
|
+
*Stephen Margheim*
|
2291
689
|
|
2292
|
-
|
690
|
+
* Remove warning message when running SQLite in production, but leave it unconfigured.
|
2293
691
|
|
2294
|
-
|
692
|
+
There are valid use cases for running SQLite in production. However, it must be done
|
693
|
+
with care, so instead of a warning most users won't see anyway, it's preferable to
|
694
|
+
leave the configuration commented out to force them to think about having the database
|
695
|
+
on a persistent volume etc.
|
2295
696
|
|
2296
|
-
|
2297
|
-
applications to specify the job that will be used to destroy associated
|
2298
|
-
records in the background for `has_many` associations with the
|
2299
|
-
`dependent: :destroy_async` option. Previously, that was ignored, which
|
2300
|
-
meant the default `ActiveRecord::DestroyAssociationAsyncJob` always
|
2301
|
-
destroyed records in the background.
|
697
|
+
*Jacopo Beschi*, *Jean Boussier*
|
2302
698
|
|
2303
|
-
|
699
|
+
* Add support for generated columns to the SQLite3 adapter.
|
2304
700
|
|
2305
|
-
|
701
|
+
Generated columns (both stored and dynamic) are supported since version 3.31.0 of SQLite.
|
702
|
+
This adds support for those to the SQLite3 adapter.
|
2306
703
|
|
2307
|
-
|
704
|
+
```ruby
|
705
|
+
create_table :users do |t|
|
706
|
+
t.string :name
|
707
|
+
t.virtual :name_upper, type: :string, as: 'UPPER(name)'
|
708
|
+
t.virtual :name_lower, type: :string, as: 'LOWER(name)', stored: true
|
709
|
+
end
|
710
|
+
```
|
2308
711
|
|
2309
|
-
*
|
712
|
+
*Stephen Margheim*
|
2310
713
|
|
2311
|
-
|
714
|
+
* TrilogyAdapter: ignore `host` if `socket` parameter is set.
|
2312
715
|
|
2313
|
-
|
716
|
+
This allows to configure a connection on a UNIX socket via `DATABASE_URL`:
|
2314
717
|
|
2315
|
-
|
718
|
+
```
|
719
|
+
DATABASE_URL=trilogy://does-not-matter/my_db_production?socket=/var/run/mysql.sock
|
720
|
+
```
|
2316
721
|
|
2317
|
-
*
|
722
|
+
*Jean Boussier*
|
2318
723
|
|
2319
|
-
|
724
|
+
* Make `assert_queries_count`, `assert_no_queries`, `assert_queries_match`, and
|
725
|
+
`assert_no_queries_match` assertions public.
|
2320
726
|
|
2321
|
-
|
727
|
+
To assert the expected number of queries are made, Rails internally uses `assert_queries_count` and
|
728
|
+
`assert_no_queries`. To assert that specific SQL queries are made, `assert_queries_match` and
|
729
|
+
`assert_no_queries_match` are used. These assertions can now be used in applications as well.
|
2322
730
|
|
2323
|
-
|
2324
|
-
|
731
|
+
```ruby
|
732
|
+
class ArticleTest < ActiveSupport::TestCase
|
733
|
+
test "queries are made" do
|
734
|
+
assert_queries_count(1) { Article.first }
|
735
|
+
end
|
2325
736
|
|
2326
|
-
|
2327
|
-
|
737
|
+
test "creates a foreign key" do
|
738
|
+
assert_queries_match(/ADD FOREIGN KEY/i, include_schema: true) do
|
739
|
+
@connection.add_foreign_key(:comments, :posts)
|
740
|
+
end
|
741
|
+
end
|
742
|
+
end
|
743
|
+
```
|
2328
744
|
|
2329
|
-
*
|
745
|
+
*Petrik de Heus*, *fatkodima*
|
2330
746
|
|
2331
|
-
* Fix
|
747
|
+
* Fix `has_secure_token` calls the setter method on initialize.
|
2332
748
|
|
2333
|
-
|
749
|
+
*Abeid Ahmed*
|
2334
750
|
|
2335
|
-
|
751
|
+
* When using a `DATABASE_URL`, allow for a configuration to map the protocol in the URL to a specific database
|
752
|
+
adapter. This allows decoupling the adapter the application chooses to use from the database connection details
|
753
|
+
set in the deployment environment.
|
2336
754
|
|
2337
|
-
|
755
|
+
```ruby
|
756
|
+
# ENV['DATABASE_URL'] = "mysql://localhost/example_database"
|
757
|
+
config.active_record.protocol_adapters.mysql = "trilogy"
|
758
|
+
# will connect to MySQL using the trilogy adapter
|
759
|
+
```
|
2338
760
|
|
2339
|
-
|
2340
|
-
issued for both real transactions and savepoints. This breaks MySQL which
|
2341
|
-
disallows rollbacks of savepoints following a deadlock.
|
761
|
+
*Jean Boussier*, *Kevin McPhillips*
|
2342
762
|
|
2343
|
-
|
2344
|
-
the
|
763
|
+
* In cases where MySQL returns `warning_count` greater than zero, but returns no warnings when
|
764
|
+
the `SHOW WARNINGS` query is executed, `ActiveRecord.db_warnings_action` proc will still be
|
765
|
+
called with a generic warning message rather than silently ignoring the warning(s).
|
2345
766
|
|
2346
|
-
|
767
|
+
*Kevin McPhillips*
|
2347
768
|
|
2348
|
-
|
769
|
+
* `DatabaseConfigurations#configs_for` accepts a symbol in the `name` parameter.
|
2349
770
|
|
2350
|
-
*
|
771
|
+
*Andrew Novoselac*
|
2351
772
|
|
2352
|
-
|
2353
|
-
|
2354
|
-
|
773
|
+
* Fix `where(field: values)` queries when `field` is a serialized attribute
|
774
|
+
(for example, when `field` uses `ActiveRecord::Base.serialize` or is a JSON
|
775
|
+
column).
|
2355
776
|
|
2356
|
-
*
|
777
|
+
*João Alves*
|
2357
778
|
|
2358
|
-
*
|
779
|
+
* Make the output of `ActiveRecord::Core#inspect` configurable.
|
2359
780
|
|
2360
|
-
|
781
|
+
By default, calling `inspect` on a record will yield a formatted string including just the `id`.
|
2361
782
|
|
2362
783
|
```ruby
|
2363
|
-
|
2364
|
-
before_save :check_title
|
2365
|
-
|
2366
|
-
def check_title
|
2367
|
-
throw(:abort) if title == "abort"
|
2368
|
-
end
|
2369
|
-
end
|
2370
|
-
|
2371
|
-
topic = Topic.create(title: "Test Title")
|
2372
|
-
# #=> #<Topic title: "Test Title">
|
2373
|
-
topic.update_attribute!(:title, "Another Title")
|
2374
|
-
# #=> #<Topic title: "Another Title">
|
2375
|
-
topic.update_attribute!(:title, "abort")
|
2376
|
-
# raises ActiveRecord::RecordNotSaved
|
784
|
+
Post.first.inspect #=> "#<Post id: 1>"
|
2377
785
|
```
|
2378
786
|
|
2379
|
-
|
2380
|
-
|
2381
|
-
* Avoid loading every record in `ActiveRecord::Relation#pretty_print`
|
787
|
+
The attributes to be included in the output of `inspect` can be configured with
|
788
|
+
`ActiveRecord::Core#attributes_for_inspect`.
|
2382
789
|
|
2383
790
|
```ruby
|
2384
|
-
|
2385
|
-
|
2386
|
-
|
2387
|
-
# After
|
2388
|
-
pp Foo.all # Shows 10 items and an ellipsis.
|
791
|
+
Post.attributes_for_inspect = [:id, :title]
|
792
|
+
Post.first.inspect #=> "#<Post id: 1, title: "Hello, World!">"
|
2389
793
|
```
|
2390
794
|
|
2391
|
-
|
2392
|
-
|
2393
|
-
* Change `QueryMethods#in_order_of` to drop records not listed in values.
|
2394
|
-
|
2395
|
-
`in_order_of` now filters down to the values provided, to match the behavior of the `Enumerable` version.
|
2396
|
-
|
2397
|
-
*Kevin Newton*
|
2398
|
-
|
2399
|
-
* Allow named expression indexes to be revertible.
|
2400
|
-
|
2401
|
-
Previously, the following code would raise an error in a reversible migration executed while rolling back, due to the index name not being used in the index removal.
|
795
|
+
With `attributes_for_inspect` set to `:all`, `inspect` will list all the record's attributes.
|
2402
796
|
|
2403
797
|
```ruby
|
2404
|
-
|
798
|
+
Post.attributes_for_inspect = :all
|
799
|
+
Post.first.inspect #=> "#<Post id: 1, title: "Hello, World!", published_at: "2023-10-23 14:28:11 +0000">"
|
2405
800
|
```
|
2406
801
|
|
2407
|
-
|
802
|
+
In `development` and `test` mode, `attributes_for_inspect` will be set to `:all` by default.
|
2408
803
|
|
2409
|
-
|
804
|
+
You can also call `full_inspect` to get an inspection with all the attributes.
|
2410
805
|
|
2411
|
-
|
806
|
+
The attributes in `attribute_for_inspect` will also be used for `pretty_print`.
|
2412
807
|
|
2413
|
-
|
808
|
+
*Andrew Novoselac*
|
809
|
+
|
810
|
+
* Don't mark attributes as changed when reassigned to `Float::INFINITY` or
|
811
|
+
`-Float::INFINITY`.
|
2414
812
|
|
2415
|
-
*
|
813
|
+
*Maicol Bentancor*
|
2416
814
|
|
2417
|
-
*
|
815
|
+
* Support the `RETURNING` clause for MariaDB.
|
2418
816
|
|
2419
|
-
|
2420
|
-
bigint instead of integer for the SQLite Adapter.
|
817
|
+
*fatkodima*, *Nikolay Kondratyev*
|
2421
818
|
|
2422
|
-
|
819
|
+
* The SQLite3 adapter now implements the `supports_deferrable_constraints?` contract.
|
2423
820
|
|
2424
|
-
|
821
|
+
Allows foreign keys to be deferred by adding the `:deferrable` key to the `foreign_key` options.
|
2425
822
|
|
2426
823
|
```ruby
|
2427
|
-
|
824
|
+
add_reference :person, :alias, foreign_key: { deferrable: :deferred }
|
825
|
+
add_reference :alias, :person, foreign_key: { deferrable: :deferred }
|
2428
826
|
```
|
2429
827
|
|
2430
|
-
|
2431
|
-
value is still ordered.
|
2432
|
-
|
2433
|
-
*Jean Boussier*
|
2434
|
-
|
2435
|
-
* Fix quoting of column aliases generated by calculation methods.
|
828
|
+
*Stephen Margheim*
|
2436
829
|
|
2437
|
-
|
2438
|
-
is a valid identifier.
|
830
|
+
* Add the `set_constraints` helper to PostgreSQL connections.
|
2439
831
|
|
2440
832
|
```ruby
|
2441
|
-
|
2442
|
-
|
833
|
+
Post.create!(user_id: -1) # => ActiveRecord::InvalidForeignKey
|
834
|
+
|
835
|
+
Post.transaction do
|
836
|
+
Post.connection.set_constraints(:deferred)
|
837
|
+
p = Post.create!(user_id: -1)
|
838
|
+
u = User.create!
|
839
|
+
p.user = u
|
840
|
+
p.save!
|
2443
841
|
end
|
2444
|
-
Test.group(:id).count
|
2445
|
-
# syntax error at or near "1" (ActiveRecord::StatementInvalid)
|
2446
|
-
# LINE 1: SELECT COUNT(*) AS count_all, "1abc"."id" AS 1abc_id FROM "1...
|
2447
842
|
```
|
2448
843
|
|
2449
|
-
*
|
844
|
+
*Cody Cutrer*
|
2450
845
|
|
2451
|
-
*
|
846
|
+
* Include `ActiveModel::API` in `ActiveRecord::Base`.
|
2452
847
|
|
2453
|
-
|
2454
|
-
returns early when a user with a matching email is not found:
|
848
|
+
*Sean Doyle*
|
2455
849
|
|
2456
|
-
|
2457
|
-
|
2458
|
-
|
850
|
+
* Ensure `#signed_id` outputs `url_safe` strings.
|
851
|
+
|
852
|
+
*Jason Meller*
|
2459
853
|
|
2460
|
-
|
2461
|
-
attacker can determine if a user account with a given email exists. After
|
2462
|
-
confirming that an account exists, the attacker can try passwords associated
|
2463
|
-
with that email address from other leaked databases, in case the user
|
2464
|
-
re-used a password across multiple sites (a common practice). Additionally,
|
2465
|
-
knowing an account email address allows the attacker to attempt a targeted
|
2466
|
-
phishing ("spear phishing") attack.
|
854
|
+
* Add `nulls_last` and working `desc.nulls_first` for MySQL.
|
2467
855
|
|
2468
|
-
|
2469
|
-
|
856
|
+
*Tristan Fellows*
|
857
|
+
|
858
|
+
* Allow for more complex hash arguments for `order` which mimics `where` in `ActiveRecord::Relation`.
|
2470
859
|
|
2471
860
|
```ruby
|
2472
|
-
|
861
|
+
Topic.includes(:posts).order(posts: { created_at: :desc })
|
2473
862
|
```
|
2474
863
|
|
2475
|
-
*
|
2476
|
-
|
864
|
+
*Myles Boone*
|
2477
865
|
|
2478
|
-
Please check [7-
|
866
|
+
Please check [7-1-stable](https://github.com/rails/rails/blob/7-1-stable/activerecord/CHANGELOG.md) for previous changes.
|