activerecord 7.0.0.alpha1 → 7.0.0.rc3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +516 -10
  3. data/lib/active_record/associations/association.rb +2 -8
  4. data/lib/active_record/associations/builder/collection_association.rb +9 -2
  5. data/lib/active_record/associations/collection_association.rb +10 -2
  6. data/lib/active_record/associations/preloader/association.rb +68 -48
  7. data/lib/active_record/associations/preloader/batch.rb +3 -6
  8. data/lib/active_record/associations/preloader/through_association.rb +19 -9
  9. data/lib/active_record/associations/preloader.rb +14 -24
  10. data/lib/active_record/associations/through_association.rb +2 -2
  11. data/lib/active_record/associations.rb +16 -3
  12. data/lib/active_record/asynchronous_queries_tracker.rb +3 -0
  13. data/lib/active_record/attribute_methods/dirty.rb +9 -1
  14. data/lib/active_record/attribute_methods.rb +7 -5
  15. data/lib/active_record/autosave_association.rb +3 -3
  16. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +6 -26
  17. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -2
  18. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +18 -5
  19. data/lib/active_record/connection_adapters/abstract/database_limits.rb +0 -17
  20. data/lib/active_record/connection_adapters/abstract/database_statements.rb +1 -1
  21. data/lib/active_record/connection_adapters/abstract/quoting.rb +33 -70
  22. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +4 -0
  23. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +9 -2
  24. data/lib/active_record/connection_adapters/abstract/transaction.rb +12 -19
  25. data/lib/active_record/connection_adapters/abstract_adapter.rb +37 -8
  26. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +1 -0
  27. data/lib/active_record/connection_adapters/column.rb +4 -0
  28. data/lib/active_record/connection_adapters/mysql/database_statements.rb +2 -2
  29. data/lib/active_record/connection_adapters/mysql/quoting.rb +23 -24
  30. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +1 -1
  31. data/lib/active_record/connection_adapters/pool_config.rb +7 -5
  32. data/lib/active_record/connection_adapters/postgresql/column.rb +17 -1
  33. data/lib/active_record/connection_adapters/postgresql/quoting.rb +44 -44
  34. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +21 -1
  35. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +18 -1
  36. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +25 -0
  37. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +15 -4
  38. data/lib/active_record/connection_adapters/postgresql_adapter.rb +48 -5
  39. data/lib/active_record/connection_adapters/schema_cache.rb +3 -1
  40. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +2 -2
  41. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +15 -16
  42. data/lib/active_record/connection_handling.rb +31 -19
  43. data/lib/active_record/core.rb +13 -24
  44. data/lib/active_record/database_configurations/connection_url_resolver.rb +2 -1
  45. data/lib/active_record/database_configurations/database_config.rb +0 -9
  46. data/lib/active_record/database_configurations/hash_config.rb +40 -8
  47. data/lib/active_record/database_configurations.rb +2 -27
  48. data/lib/active_record/delegated_type.rb +19 -0
  49. data/lib/active_record/encryption/encrypted_attribute_type.rb +1 -1
  50. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +1 -2
  51. data/lib/active_record/encryption/message_serializer.rb +11 -1
  52. data/lib/active_record/encryption/scheme.rb +1 -1
  53. data/lib/active_record/enum.rb +8 -1
  54. data/lib/active_record/errors.rb +1 -1
  55. data/lib/active_record/explain_registry.rb +11 -6
  56. data/lib/active_record/fixture_set/table_row.rb +1 -1
  57. data/lib/active_record/fixtures.rb +1 -9
  58. data/lib/active_record/future_result.rb +2 -2
  59. data/lib/active_record/gem_version.rb +1 -1
  60. data/lib/active_record/insert_all.rb +52 -15
  61. data/lib/active_record/integration.rb +3 -2
  62. data/lib/active_record/legacy_yaml_adapter.rb +2 -39
  63. data/lib/active_record/locking/pessimistic.rb +9 -3
  64. data/lib/active_record/log_subscriber.rb +8 -1
  65. data/lib/active_record/middleware/shard_selector.rb +60 -0
  66. data/lib/active_record/model_schema.rb +1 -28
  67. data/lib/active_record/nested_attributes.rb +11 -10
  68. data/lib/active_record/no_touching.rb +1 -1
  69. data/lib/active_record/persistence.rb +99 -21
  70. data/lib/active_record/query_logs.rb +18 -83
  71. data/lib/active_record/railtie.rb +11 -1
  72. data/lib/active_record/railties/databases.rake +4 -91
  73. data/lib/active_record/reflection.rb +22 -6
  74. data/lib/active_record/relation/calculations.rb +1 -10
  75. data/lib/active_record/relation/finder_methods.rb +0 -13
  76. data/lib/active_record/relation/query_methods.rb +5 -14
  77. data/lib/active_record/relation/record_fetch_warning.rb +5 -7
  78. data/lib/active_record/relation/where_clause.rb +2 -15
  79. data/lib/active_record/relation.rb +11 -13
  80. data/lib/active_record/result.rb +0 -5
  81. data/lib/active_record/runtime_registry.rb +10 -12
  82. data/lib/active_record/schema_dumper.rb +7 -0
  83. data/lib/active_record/scoping.rb +34 -22
  84. data/lib/active_record/suppressor.rb +11 -15
  85. data/lib/active_record/tasks/database_tasks.rb +18 -44
  86. data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -1
  87. data/lib/active_record/validations/uniqueness.rb +1 -1
  88. data/lib/active_record.rb +41 -33
  89. data/lib/arel/crud.rb +12 -2
  90. data/lib/arel/delete_manager.rb +16 -0
  91. data/lib/arel/filter_predications.rb +9 -0
  92. data/lib/arel/nodes/delete_statement.rb +5 -1
  93. data/lib/arel/nodes/filter.rb +10 -0
  94. data/lib/arel/nodes/function.rb +1 -0
  95. data/lib/arel/nodes/update_statement.rb +5 -1
  96. data/lib/arel/nodes.rb +1 -0
  97. data/lib/arel/predications.rb +10 -2
  98. data/lib/arel/update_manager.rb +16 -0
  99. data/lib/arel/visitors/mysql.rb +2 -1
  100. data/lib/arel/visitors/to_sql.rb +15 -0
  101. data/lib/arel.rb +1 -0
  102. metadata +17 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b8b1381be32717b39c0060b1d2fe294fa5bd782565949f7ef9d106dff7de7caa
4
- data.tar.gz: 003b65d0b2e4b6ac2492bd5249b1bb609173c5885dee85fc3caa6ab7ae9512e6
3
+ metadata.gz: 458dd96fbc8713da75b5ee24f47f90b3330c3baf9f5ce2db5bda1eb2c5ca3c01
4
+ data.tar.gz: fc473846b0d1ee465223c5980616937a119ef0ce349154ca4c0eb3633db0790a
5
5
  SHA512:
6
- metadata.gz: 942850951ae80edc566d1748d560e5928d1e541081c74f43a771226f50d95a3f82f119b1e47d74ef1d328d6374ab0cddb6e87df849fec3e9765990fe9983b958
7
- data.tar.gz: 017cae0c0f11441244b2d505aeca4c9157e3fd6458a58ca49910f3158df5a45ab6d0401a36cacca046200bec484dc7434d9b2416feced753cbbf89587dcb9a2b
6
+ metadata.gz: 1f7d111235cf366f0de47a9f895d8a01351344b52d5a92dda94e627e424d7b9ed72daec2b371f58fa5d7d2e99de8bb8add753aa16baca7977a1a3174443b5171
7
+ data.tar.gz: 573befa4bc581ae039212f43f7c622f64a19900de064579f6314b2351457e64b74cfc5d63b37c06058da394244d585d8271f6b1f22b8646e4138e145d8b4b4d1
data/CHANGELOG.md CHANGED
@@ -1,3 +1,509 @@
1
+ ## Rails 7.0.0.rc3 (December 14, 2021) ##
2
+
3
+ * No changes.
4
+
5
+
6
+ ## Rails 7.0.0.rc2 (December 14, 2021) ##
7
+
8
+ * Remove deprecated `ActiveRecord::DatabaseConfigurations::DatabaseConfig#spec_name`.
9
+
10
+ *Rafael Mendonça França*
11
+
12
+ * Remove deprecated `ActiveRecord::Connection#in_clause_length`.
13
+
14
+ *Rafael Mendonça França*
15
+
16
+ * Remove deprecated `ActiveRecord::Connection#allowed_index_name_length`.
17
+
18
+ *Rafael Mendonça França*
19
+
20
+ * Remove deprecated `ActiveRecord::Base#remove_connection`.
21
+
22
+ *Rafael Mendonça França*
23
+
24
+ * Load STI Models in fixtures
25
+
26
+ Data from Fixtures now loads based on the specific class for models with
27
+ Single Table Inheritance. This affects enums defined in subclasses, previously
28
+ the value of these fields was not parsed and remained `nil`
29
+
30
+ *Andres Howard*
31
+
32
+ * `#authenticate` returns false when the password is blank instead of raising an error.
33
+
34
+ *Muhammad Muhammad Ibrahim*
35
+
36
+ * Fix `ActiveRecord::QueryMethods#in_order_of` behavior for integer enums.
37
+
38
+ `ActiveRecord::QueryMethods#in_order_of` didn't work as expected for enums stored as integers in the database when passing an array of strings or symbols as the order argument. This unexpected behavior occurred because the string or symbol values were not casted to match the integers in the database.
39
+
40
+ The following example now works as expected:
41
+
42
+ ```ruby
43
+ class Book < ApplicationRecord
44
+ enum status: [:proposed, :written, :published]
45
+ end
46
+
47
+ Book.in_order_of(:status, %w[written published proposed])
48
+ ```
49
+
50
+ *Alexandre Ruban*
51
+
52
+ * Ignore persisted in-memory records when merging target lists.
53
+
54
+ *Kevin Sjöberg*
55
+
56
+ * Add a new option `:update_only` to `upsert_all` to configure the list of columns to update in case of conflict.
57
+
58
+ Before, you could only customize the update SQL sentence via `:on_duplicate`. There is now a new option `:update_only` that lets you provide a list of columns to update in case of conflict:
59
+
60
+ ```ruby
61
+ Commodity.upsert_all(
62
+ [
63
+ { id: 2, name: "Copper", price: 4.84 },
64
+ { id: 4, name: "Gold", price: 1380.87 },
65
+ { id: 6, name: "Aluminium", price: 0.35 }
66
+ ],
67
+ update_only: [:price] # Only prices will be updated
68
+ )
69
+ ```
70
+
71
+ *Jorge Manrubia*
72
+
73
+ * Remove deprecated `ActiveRecord::Result#map!` and `ActiveRecord::Result#collect!`.
74
+
75
+ *Rafael Mendonça França*
76
+
77
+ * Remove deprecated `ActiveRecord::Base.configurations.to_h`.
78
+
79
+ *Rafael Mendonça França*
80
+
81
+ * Remove deprecated `ActiveRecord::Base.configurations.default_hash`.
82
+
83
+ *Rafael Mendonça França*
84
+
85
+ * Remove deprecated `ActiveRecord::Base.arel_attribute`.
86
+
87
+ *Rafael Mendonça França*
88
+
89
+ * Remove deprecated `ActiveRecord::Base.connection_config`.
90
+
91
+ *Rafael Mendonça França*
92
+
93
+ * Filter attributes in SQL logs
94
+
95
+ Previously, SQL queries in logs containing `ActiveRecord::Base.filter_attributes` were not filtered.
96
+
97
+ Now, the filter attributes will be masked `[FILTERED]` in the logs when `prepared_statement` is enabled.
98
+
99
+ ```
100
+ # Before:
101
+ Foo Load (0.2ms) SELECT "foos".* FROM "foos" WHERE "foos"."passw" = ? LIMIT ? [["passw", "hello"], ["LIMIT", 1]]
102
+
103
+ # After:
104
+ Foo Load (0.5ms) SELECT "foos".* FROM "foos" WHERE "foos"."passw" = ? LIMIT ? [["passw", "[FILTERED]"], ["LIMIT", 1]]
105
+ ```
106
+
107
+ *Aishwarya Subramanian*
108
+
109
+ * Remove deprecated `Tasks::DatabaseTasks.spec`.
110
+
111
+ *Rafael Mendonça França*
112
+
113
+ * Remove deprecated `Tasks::DatabaseTasks.current_config`.
114
+
115
+ *Rafael Mendonça França*
116
+
117
+ * Deprecate `Tasks::DatabaseTasks.schema_file_type`.
118
+
119
+ *Rafael Mendonça França*
120
+
121
+ * Remove deprecated `Tasks::DatabaseTasks.dump_filename`.
122
+
123
+ *Rafael Mendonça França*
124
+
125
+ * Remove deprecated `Tasks::DatabaseTasks.schema_file`.
126
+
127
+ *Rafael Mendonça França*
128
+
129
+ * Remove deprecated `environment` and `name` arguments from `Tasks::DatabaseTasks.schema_up_to_date?`.
130
+
131
+ *Rafael Mendonça França*
132
+
133
+ * Merging conditions on the same column no longer maintain both conditions,
134
+ and will be consistently replaced by the latter condition.
135
+
136
+ ```ruby
137
+ # Rails 6.1 (IN clause is replaced by merger side equality condition)
138
+ Author.where(id: [david.id, mary.id]).merge(Author.where(id: bob)) # => [bob]
139
+ # Rails 6.1 (both conflict conditions exists, deprecated)
140
+ Author.where(id: david.id..mary.id).merge(Author.where(id: bob)) # => []
141
+ # Rails 6.1 with rewhere to migrate to Rails 7.0's behavior
142
+ Author.where(id: david.id..mary.id).merge(Author.where(id: bob), rewhere: true) # => [bob]
143
+ # Rails 7.0 (same behavior with IN clause, mergee side condition is consistently replaced)
144
+ Author.where(id: [david.id, mary.id]).merge(Author.where(id: bob)) # => [bob]
145
+ Author.where(id: david.id..mary.id).merge(Author.where(id: bob)) # => [bob]
146
+
147
+ *Rafael Mendonça França*
148
+
149
+ * Remove deprecated support to `Model.reorder(nil).first` to search using non-deterministic order.
150
+
151
+ *Rafael Mendonça França*
152
+
153
+ * Remove deprecated rake tasks:
154
+
155
+ * `db:schema:load_if_ruby`
156
+ * `db:structure:dump`
157
+ * `db:structure:load`
158
+ * `db:structure:load_if_sql`
159
+ * `db:structure:dump:#{name}`
160
+ * `db:structure:load:#{name}`
161
+ * `db:test:load_structure`
162
+ * `db:test:load_structure:#{name}`
163
+
164
+ *Rafael Mendonça França*
165
+
166
+ * Remove deprecated `DatabaseConfig#config` method.
167
+
168
+ *Rafael Mendonça França*
169
+
170
+ * Rollback transactions when the block returns earlier than expected.
171
+
172
+ Before this change, when a transaction block returned early, the transaction would be committed.
173
+
174
+ The problem is that timeouts triggered inside the transaction block was also making the incomplete transaction
175
+ to be committed, so in order to avoid this mistake, the transaction block is rolled back.
176
+
177
+ *Rafael Mendonça França*
178
+
179
+ * Add middleware for automatic shard swapping.
180
+
181
+ Provides a basic middleware to perform automatic shard swapping. Applications will provide a resolver which will determine for an individual request which shard should be used. Example:
182
+
183
+ ```ruby
184
+ config.active_record.shard_resolver = ->(request) {
185
+ subdomain = request.subdomain
186
+ tenant = Tenant.find_by_subdomain!(subdomain)
187
+ tenant.shard
188
+ }
189
+ ```
190
+
191
+ See guides for more details.
192
+
193
+ *Eileen M. Uchitelle*, *John Crepezzi*
194
+
195
+ * Remove deprecated support to pass a column to `type_cast`.
196
+
197
+ *Rafael Mendonça França*
198
+
199
+ * Remove deprecated support to type cast to database values `ActiveRecord::Base` objects.
200
+
201
+ *Rafael Mendonça França*
202
+
203
+ * Remove deprecated support to quote `ActiveRecord::Base` objects.
204
+
205
+ *Rafael Mendonça França*
206
+
207
+ * Remove deprecacated support to resolve connection using `"primary"` as connection specification name.
208
+
209
+ *Rafael Mendonça França*
210
+
211
+ * Remove deprecation warning when using `:interval` column is used in PostgreSQL database.
212
+
213
+ Now, interval columns will return `ActiveSupport::Duration` objects instead of strings.
214
+
215
+ To keep the old behavior, you can add this line to your model:
216
+
217
+ ```ruby
218
+ attribute :column, :string
219
+ ```
220
+
221
+ *Rafael Mendonça França*
222
+
223
+ * Remove deprecated support to YAML load `ActiveRecord::Base` instance in the Rails 4.2 and 4.1 formats.
224
+
225
+ *Rafael Mendonça França*
226
+
227
+ * Remove deprecated option `:spec_name` in the `configs_for` method.
228
+
229
+ *Rafael Mendonça França*
230
+
231
+ * Remove deprecated `ActiveRecord::Base.allow_unsafe_raw_sql`.
232
+
233
+ *Rafael Mendonça França*
234
+
235
+ * Fix regression bug that caused ignoring additional conditions for preloading has_many-through relations.
236
+
237
+ Fixes #43132
238
+
239
+ *Alexander Pauly*
240
+
241
+ * Fix `has_many` inversing recursion on models with recursive associations.
242
+
243
+ *Gannon McGibbon*
244
+
245
+ * Add `accepts_nested_attributes_for` support for `delegated_type`
246
+
247
+ ```ruby
248
+ class Entry < ApplicationRecord
249
+ delegated_type :entryable, types: %w[ Message Comment ]
250
+ accepts_nested_attributes_for :entryable
251
+ end
252
+
253
+ entry = Entry.create(entryable_type: 'Message', entryable_attributes: { content: 'Hello world' })
254
+ # => #<Entry:0x00>
255
+ # id: 1
256
+ # entryable_id: 1,
257
+ # entryable_type: 'Message'
258
+ # ...>
259
+
260
+ entry.entryable
261
+ # => #<Message:0x01>
262
+ # id: 1
263
+ # content: 'Hello world'
264
+ # ...>
265
+ ```
266
+
267
+ Previously it would raise an error:
268
+
269
+ ```ruby
270
+ Entry.create(entryable_type: 'Message', entryable_attributes: { content: 'Hello world' })
271
+ # ArgumentError: Cannot build association `entryable'. Are you trying to build a polymorphic one-to-one association?
272
+ ```
273
+
274
+ *Sjors Baltus*
275
+
276
+ * Use subquery for DELETE with GROUP_BY and HAVING clauses.
277
+
278
+ Prior to this change, deletes with GROUP_BY and HAVING were returning an error.
279
+
280
+ After this change, GROUP_BY and HAVING are valid clauses in DELETE queries, generating the following query:
281
+
282
+ ```sql
283
+ DELETE FROM "posts" WHERE "posts"."id" IN (
284
+ SELECT "posts"."id" FROM "posts" INNER JOIN "comments" ON "comments"."post_id" = "posts"."id" GROUP BY "posts"."id" HAVING (count(comments.id) >= 2))
285
+ ) [["flagged", "t"]]
286
+ ```
287
+
288
+ *Ignacio Chiazzo Cardarello*
289
+
290
+ * Use subquery for UPDATE with GROUP_BY and HAVING clauses.
291
+
292
+ Prior to this change, updates with GROUP_BY and HAVING were being ignored, generating a SQL like this:
293
+
294
+ ```sql
295
+ UPDATE "posts" SET "flagged" = ? WHERE "posts"."id" IN (
296
+ SELECT "posts"."id" FROM "posts" INNER JOIN "comments" ON "comments"."post_id" = "posts"."id"
297
+ ) [["flagged", "t"]]
298
+ ```
299
+
300
+ After this change, GROUP_BY and HAVING clauses are used as a subquery in updates, like this:
301
+
302
+ ```sql
303
+ UPDATE "posts" SET "flagged" = ? WHERE "posts"."id" IN (
304
+ SELECT "posts"."id" FROM "posts" INNER JOIN "comments" ON "comments"."post_id" = "posts"."id"
305
+ GROUP BY posts.id HAVING (count(comments.id) >= 2)
306
+ ) [["flagged", "t"]]
307
+ ```
308
+
309
+ *Ignacio Chiazzo Cardarello*
310
+
311
+ * Add support for setting the filename of the schema or structure dump in the database config.
312
+
313
+ Applications may now set their the filename or path of the schema / structure dump file in their database configuration.
314
+
315
+
316
+ ```yaml
317
+ production:
318
+ primary:
319
+ database: my_db
320
+ schema_dump: my_schema_dump_filename.rb
321
+ animals:
322
+ database: animals_db
323
+ schema_dump: false
324
+ ```
325
+
326
+ The filename set in `schema_dump` will be used by the application. If set to `false` the schema will not be dumped. The database tasks are responsible for adding the database directory to the filename. If a full path is provided, the Rails tasks will use that instead of `ActiveRecord::DatabaseTasks.db_dir`.
327
+
328
+ *Eileen M. Uchitelle*, *Ryan Kerr*
329
+
330
+ * Add `ActiveRecord::Base.prohibit_shard_swapping` to prevent attempts to change the shard within a block.
331
+
332
+ *John Crepezzi*, *Eileen M. Uchitelle*
333
+
334
+ * Filter unchanged attributes with default function from insert query when `partial_inserts` is disabled.
335
+
336
+ *Akshay Birajdar*, *Jacopo Beschi*
337
+
338
+ * Add support for FILTER clause (SQL:2003) to Arel.
339
+
340
+ Currently supported by PostgreSQL 9.4+ and SQLite 3.30+.
341
+
342
+ *Andrey Novikov*
343
+
344
+ * Automatically set timestamps on record creation during bulk insert/upsert
345
+
346
+ Prior to this change, only updates during an upsert operation (e.g. `upsert_all`) would touch timestamps (`updated_{at,on}`). Now, record creations also touch timestamp columns (`{created,updated}_{at,on}`).
347
+
348
+ This behaviour is controlled by the `<model>.record_timestamps` config, matching the behaviour of `create`, `update`, etc. It can also be overridden by using the `record_timestamps:` keyword argument.
349
+
350
+ Note that this means `upsert_all` on models with `record_timestamps = false` will no longer touch `updated_{at,on}` automatically.
351
+
352
+ *Sam Bostock*
353
+
354
+ * Don't require `role` when passing `shard` to `connected_to`.
355
+
356
+ `connected_to` can now be called with a `shard` only. Note that `role` is still inherited if `connected_to` calls are nested.
357
+
358
+ *Eileen M. Uchitelle*
359
+
360
+ * Add option to lazily load the schema cache on the connection.
361
+
362
+ Previously, the only way to load the schema cache in Active Record was through the Railtie on boot. This option provides the ability to load the schema cache on the connection after it's been established. Loading the cache lazily on the connection can be beneficial for Rails applications that use multiple databases because it will load the cache at the time the connection is established. Currently Railties doesn't have access to the connections before boot.
363
+
364
+ To use the cache, set `config.active_record.lazily_load_schema_cache = true` in your application configuration. In addition a `schema_cache_path` should be set in your database configuration if you don't want to use the default "db/schema_cache.yml" path.
365
+
366
+ *Eileen M. Uchitelle*
367
+
368
+ * Allow automatic `inverse_of` detection for associations with scopes.
369
+
370
+ Automatic `inverse_of` detection now works for associations with scopes. For
371
+ example, the `comments` association here now automatically detects
372
+ `inverse_of: :post`, so we don't need to pass that option:
373
+
374
+ ```ruby
375
+ class Post < ActiveRecord::Base
376
+ has_many :comments, -> { visible }
377
+ end
378
+
379
+ class Comment < ActiveRecord::Base
380
+ belongs_to :post
381
+ end
382
+ ```
383
+
384
+ Note that the automatic detection still won't work if the inverse
385
+ association has a scope. In this example a scope on the `post` association
386
+ would still prevent Rails from finding the inverse for the `comments`
387
+ association.
388
+
389
+ This will be the default for new apps in Rails 7. To opt in:
390
+
391
+ ```ruby
392
+ config.active_record.automatic_scope_inversing = true
393
+ ```
394
+
395
+ *Daniel Colson*, *Chris Bloom*
396
+
397
+ * Accept optional transaction args to `ActiveRecord::Locking::Pessimistic#with_lock`
398
+
399
+ `#with_lock` now accepts transaction options like `requires_new:`,
400
+ `isolation:`, and `joinable:`
401
+
402
+ * Adds support for deferrable foreign key constraints in PostgreSQL.
403
+
404
+ By default, foreign key constraints in PostgreSQL are checked after each statement. This works for most use cases,
405
+ but becomes a major limitation when creating related records before the parent record is inserted into the database.
406
+ One example of this is looking up / creating a person via one or more unique alias.
407
+
408
+ ```ruby
409
+ Person.transaction do
410
+ alias = Alias
411
+ .create_with(user_id: SecureRandom.uuid)
412
+ .create_or_find_by(name: "DHH")
413
+
414
+ person = Person
415
+ .create_with(name: "David Heinemeier Hansson")
416
+ .create_or_find_by(id: alias.user_id)
417
+ end
418
+ ```
419
+
420
+ Using the default behavior, the transaction would fail when executing the first `INSERT` statement.
421
+
422
+ By passing the `:deferrable` option to the `add_foreign_key` statement in migrations, it's possible to defer this
423
+ check.
424
+
425
+ ```ruby
426
+ add_foreign_key :aliases, :person, deferrable: true
427
+ ```
428
+
429
+ Passing `deferrable: true` doesn't change the default behavior, but allows manually deferring the check using
430
+ `SET CONSTRAINTS ALL DEFERRED` within a transaction. This will cause the foreign keys to be checked after the
431
+ transaction.
432
+
433
+ It's also possible to adjust the default behavior from an immediate check (after the statement), to a deferred check
434
+ (after the transaction):
435
+
436
+ ```ruby
437
+ add_foreign_key :aliases, :person, deferrable: :deferred
438
+ ```
439
+
440
+ *Benedikt Deicke*
441
+
442
+ * Allow configuring Postgres password through the socket URL.
443
+
444
+ For example:
445
+ ```ruby
446
+ ActiveRecord::DatabaseConfigurations::UrlConfig.new(
447
+ :production, :production, 'postgres:///?user=user&password=secret&dbname=app', {}
448
+ ).configuration_hash
449
+ ```
450
+
451
+ will now return,
452
+
453
+ ```ruby
454
+ { :user=>"user", :password=>"secret", :dbname=>"app", :adapter=>"postgresql" }
455
+ ```
456
+
457
+ *Abeid Ahmed*
458
+
459
+ * PostgreSQL: support custom enum types
460
+
461
+ In migrations, use `create_enum` to add a new enum type, and `t.enum` to add a column.
462
+
463
+ ```ruby
464
+ def up
465
+ create_enum :mood, ["happy", "sad"]
466
+
467
+ change_table :cats do |t|
468
+ t.enum :current_mood, enum_type: "mood", default: "happy", null: false
469
+ end
470
+ end
471
+ ```
472
+
473
+ Enums will be presented correctly in `schema.rb`. Note that this is only supported by
474
+ the PostgreSQL adapter.
475
+
476
+ *Alex Ghiculescu*
477
+
478
+ * Avoid COMMENT statements in PostgreSQL structure dumps
479
+
480
+ COMMENT statements are now omitted from the output of `db:structure:dump` when using PostgreSQL >= 11.
481
+ This allows loading the dump without a pgsql superuser account.
482
+
483
+ Fixes #36816, #43107.
484
+
485
+ *Janosch Müller*
486
+
487
+ * Add support for generated columns in PostgreSQL adapter
488
+
489
+ Generated columns are supported since version 12.0 of PostgreSQL. This adds
490
+ support of those to the PostgreSQL adapter.
491
+
492
+ ```ruby
493
+ create_table :users do |t|
494
+ t.string :name
495
+ t.virtual :name_upcased, type: :string, as: 'upper(name)', stored: true
496
+ end
497
+ ```
498
+
499
+ *Michał Begejowicz*
500
+
501
+
502
+ ## Rails 7.0.0.alpha2 (September 15, 2021) ##
503
+
504
+ * No changes.
505
+
506
+
1
507
  ## Rails 7.0.0.alpha1 (September 15, 2021) ##
2
508
 
3
509
  * Remove warning when overwriting existing scopes
@@ -93,10 +599,10 @@
93
599
 
94
600
  The behavior now is:
95
601
 
96
- `columns`: (unchanged) raises a db error if the table does not exist
97
- `columns_hash`: (unchanged) raises a db error if the table does not exist
98
- `primary_keys`: (unchanged) returns `nil` if the table does not exist
99
- `indexes`: (changed for mysql2) returns `[]` if the table does not exist
602
+ `columns`: (unchanged) raises a db error if the table does not exist.
603
+ `columns_hash`: (unchanged) raises a db error if the table does not exist.
604
+ `primary_keys`: (unchanged) returns `nil` if the table does not exist.
605
+ `indexes`: (changed for mysql2) returns `[]` if the table does not exist.
100
606
 
101
607
  *Eileen M. Uchitelle*
102
608
 
@@ -241,7 +747,7 @@
241
747
  * Add option to disable schema dump per-database.
242
748
 
243
749
  Dumping the schema is on by default for all databases in an application. To turn it off for a
244
- specific database use the `schema_dump` option:
750
+ specific database, use the `schema_dump` option:
245
751
 
246
752
  ```yaml
247
753
  # config/database.yml
@@ -278,7 +784,7 @@
278
784
  config.active_record.partial_inserts = true
279
785
  ```
280
786
 
281
- If a migration remove the default value of a column, this option
787
+ If a migration removes the default value of a column, this option
282
788
  would cause old processes to no longer be able to create new records.
283
789
 
284
790
  If you need to remove a column, you should first use `ignored_columns`
@@ -440,7 +946,7 @@
440
946
 
441
947
  * Fix compatibility with `psych >= 4`.
442
948
 
443
- Starting in Psych 4.0.0 `YAML.load` behaves like `YAML.safe_load`. To preserve compatibility
949
+ Starting in Psych 4.0.0 `YAML.load` behaves like `YAML.safe_load`. To preserve compatibility,
444
950
  Active Record's schema cache loader and `YAMLColumn` now uses `YAML.unsafe_load` if available.
445
951
 
446
952
  *Jean Boussier*
@@ -494,7 +1000,7 @@
494
1000
 
495
1001
  ```ruby
496
1002
  class Person
497
- belongs_to :dog
1003
+ has_one :dog
498
1004
  has_one :veterinarian, through: :dog, disable_joins: true
499
1005
  end
500
1006
  ```
@@ -970,8 +1476,8 @@
970
1476
 
971
1477
  *Eileen M. Uchitelle*, *John Crepezzi*
972
1478
 
973
- * Support hash config for `structure_dump_flags` and `structure_load_flags` flags
974
- Now that Active Record supports multiple databases configuration
1479
+ * Support hash config for `structure_dump_flags` and `structure_load_flags` flags.
1480
+ Now that Active Record supports multiple databases configuration,
975
1481
  we need a way to pass specific flags for dump/load databases since
976
1482
  the options are not the same for different adapters.
977
1483
  We can use in the original way:
@@ -52,7 +52,6 @@ module ActiveRecord
52
52
  @loaded = false
53
53
  @target = nil
54
54
  @stale_state = nil
55
- @inversed = false
56
55
  end
57
56
 
58
57
  def reset_negative_cache # :nodoc:
@@ -78,7 +77,6 @@ module ActiveRecord
78
77
  def loaded!
79
78
  @loaded = true
80
79
  @stale_state = stale_state
81
- @inversed = false
82
80
  end
83
81
 
84
82
  # The target is stale if the target no longer points to the record(s) that the
@@ -88,7 +86,7 @@ module ActiveRecord
88
86
  #
89
87
  # Note that if the target has not been loaded, it is not considered stale.
90
88
  def stale_target?
91
- !@inversed && loaded? && @stale_state != stale_state
89
+ loaded? && @stale_state != stale_state
92
90
  end
93
91
 
94
92
  # Sets the target of this association to <tt>\target</tt>, and the \loaded flag to +true+.
@@ -137,15 +135,11 @@ module ActiveRecord
137
135
 
138
136
  def inversed_from(record)
139
137
  self.target = record
140
- @inversed = !!record
141
138
  end
142
139
 
143
140
  def inversed_from_queries(record)
144
141
  if inversable?(record)
145
142
  self.target = record
146
- @inversed = true
147
- else
148
- @inversed = false
149
143
  end
150
144
  end
151
145
 
@@ -295,7 +289,7 @@ module ActiveRecord
295
289
 
296
290
  # Raises ActiveRecord::AssociationTypeMismatch unless +record+ is of
297
291
  # the kind of the class of the associated objects. Meant to be used as
298
- # a sanity check when you are about to assign an associated record.
292
+ # a safety check when you are about to assign an associated record.
299
293
  def raise_on_type_mismatch!(record)
300
294
  unless record.is_a?(reflection.klass)
301
295
  fresh_class = reflection.class_name.safe_constantize
@@ -30,11 +30,18 @@ module ActiveRecord::Associations::Builder # :nodoc:
30
30
  def self.define_callback(model, callback_name, name, options)
31
31
  full_callback_name = "#{callback_name}_for_#{name}"
32
32
 
33
- unless model.method_defined?(full_callback_name)
33
+ callback_values = Array(options[callback_name.to_sym])
34
+ method_defined = model.respond_to?(full_callback_name)
35
+
36
+ # If there are no callbacks, we must also check if a superclass had
37
+ # previously defined this association
38
+ return if callback_values.empty? && !method_defined
39
+
40
+ unless method_defined
34
41
  model.class_attribute(full_callback_name, instance_accessor: false, instance_predicate: false)
35
42
  end
36
43
 
37
- callbacks = Array(options[callback_name.to_sym]).map do |callback|
44
+ callbacks = callback_values.map do |callback|
38
45
  case callback
39
46
  when Symbol
40
47
  ->(method, owner, record) { owner.send(callback, record) }
@@ -335,7 +335,7 @@ module ActiveRecord
335
335
  end
336
336
  end
337
337
 
338
- persisted + memory
338
+ persisted + memory.reject(&:persisted?)
339
339
  end
340
340
 
341
341
  def _create_record(attributes, raise = false, &block)
@@ -456,6 +456,10 @@ module ActiveRecord
456
456
 
457
457
  yield(record) if block_given?
458
458
 
459
+ if !index && @replaced_or_added_targets.include?(record)
460
+ index = @target.index(record)
461
+ end
462
+
459
463
  @replaced_or_added_targets << record if inversing || index || record.new_record?
460
464
 
461
465
  if index
@@ -480,7 +484,11 @@ module ActiveRecord
480
484
 
481
485
  def callbacks_for(callback_name)
482
486
  full_callback_name = "#{callback_name}_for_#{reflection.name}"
483
- owner.class.send(full_callback_name)
487
+ if owner.class.respond_to?(full_callback_name)
488
+ owner.class.send(full_callback_name)
489
+ else
490
+ []
491
+ end
484
492
  end
485
493
 
486
494
  def include_in_memory?(record)