activerecord 7.0.0.alpha2 → 7.0.0

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