activerecord 7.1.5.2 → 8.1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (244) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +567 -2443
  3. data/README.rdoc +16 -16
  4. data/examples/performance.rb +2 -2
  5. data/lib/active_record/association_relation.rb +3 -2
  6. data/lib/active_record/associations/alias_tracker.rb +31 -23
  7. data/lib/active_record/associations/association.rb +43 -12
  8. data/lib/active_record/associations/belongs_to_association.rb +31 -8
  9. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -2
  10. data/lib/active_record/associations/builder/association.rb +23 -11
  11. data/lib/active_record/associations/builder/belongs_to.rb +18 -4
  12. data/lib/active_record/associations/builder/collection_association.rb +7 -3
  13. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +2 -2
  14. data/lib/active_record/associations/builder/has_many.rb +3 -4
  15. data/lib/active_record/associations/builder/has_one.rb +3 -4
  16. data/lib/active_record/associations/builder/singular_association.rb +33 -5
  17. data/lib/active_record/associations/collection_association.rb +17 -9
  18. data/lib/active_record/associations/collection_proxy.rb +36 -5
  19. data/lib/active_record/associations/deprecation.rb +88 -0
  20. data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
  21. data/lib/active_record/associations/errors.rb +268 -0
  22. data/lib/active_record/associations/has_many_association.rb +1 -1
  23. data/lib/active_record/associations/has_many_through_association.rb +10 -3
  24. data/lib/active_record/associations/join_dependency/join_association.rb +1 -1
  25. data/lib/active_record/associations/join_dependency.rb +4 -2
  26. data/lib/active_record/associations/nested_error.rb +47 -0
  27. data/lib/active_record/associations/preloader/association.rb +4 -3
  28. data/lib/active_record/associations/preloader/batch.rb +7 -1
  29. data/lib/active_record/associations/preloader/branch.rb +8 -1
  30. data/lib/active_record/associations/preloader/through_association.rb +1 -3
  31. data/lib/active_record/associations/singular_association.rb +14 -3
  32. data/lib/active_record/associations/through_association.rb +1 -1
  33. data/lib/active_record/associations.rb +250 -315
  34. data/lib/active_record/asynchronous_queries_tracker.rb +28 -24
  35. data/lib/active_record/attribute_assignment.rb +0 -2
  36. data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
  37. data/lib/active_record/attribute_methods/primary_key.rb +25 -61
  38. data/lib/active_record/attribute_methods/query.rb +34 -0
  39. data/lib/active_record/attribute_methods/read.rb +1 -13
  40. data/lib/active_record/attribute_methods/serialization.rb +20 -27
  41. data/lib/active_record/attribute_methods/time_zone_conversion.rb +19 -20
  42. data/lib/active_record/attribute_methods.rb +71 -75
  43. data/lib/active_record/attributes.rb +96 -68
  44. data/lib/active_record/autosave_association.rb +93 -58
  45. data/lib/active_record/base.rb +5 -7
  46. data/lib/active_record/callbacks.rb +1 -1
  47. data/lib/active_record/coders/json.rb +14 -5
  48. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +50 -126
  49. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +16 -4
  50. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +52 -13
  51. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +681 -135
  52. data/lib/active_record/connection_adapters/abstract/database_statements.rb +165 -86
  53. data/lib/active_record/connection_adapters/abstract/query_cache.rb +226 -78
  54. data/lib/active_record/connection_adapters/abstract/quoting.rb +79 -114
  55. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +11 -7
  56. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +37 -36
  57. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -1
  58. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +136 -34
  59. data/lib/active_record/connection_adapters/abstract/transaction.rb +163 -68
  60. data/lib/active_record/connection_adapters/abstract_adapter.rb +197 -129
  61. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +112 -63
  62. data/lib/active_record/connection_adapters/column.rb +17 -4
  63. data/lib/active_record/connection_adapters/mysql/database_statements.rb +11 -3
  64. data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -57
  65. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +2 -0
  66. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +41 -10
  67. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +79 -46
  68. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +97 -101
  69. data/lib/active_record/connection_adapters/mysql2_adapter.rb +14 -33
  70. data/lib/active_record/connection_adapters/pool_config.rb +14 -13
  71. data/lib/active_record/connection_adapters/postgresql/column.rb +4 -0
  72. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +98 -44
  73. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +3 -3
  74. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
  75. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +10 -0
  76. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +1 -1
  77. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
  78. data/lib/active_record/connection_adapters/postgresql/quoting.rb +79 -68
  79. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -4
  80. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +9 -17
  81. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +44 -41
  82. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +69 -32
  83. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +155 -75
  84. data/lib/active_record/connection_adapters/postgresql_adapter.rb +104 -121
  85. data/lib/active_record/connection_adapters/schema_cache.rb +126 -133
  86. data/lib/active_record/connection_adapters/sqlite3/column.rb +14 -1
  87. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +91 -95
  88. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +57 -54
  89. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +16 -0
  90. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +13 -0
  91. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +43 -2
  92. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +38 -15
  93. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +231 -111
  94. data/lib/active_record/connection_adapters/statement_pool.rb +4 -2
  95. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +40 -69
  96. data/lib/active_record/connection_adapters/trilogy_adapter.rb +19 -65
  97. data/lib/active_record/connection_adapters.rb +66 -0
  98. data/lib/active_record/connection_handling.rb +88 -46
  99. data/lib/active_record/core.rb +142 -58
  100. data/lib/active_record/counter_cache.rb +52 -18
  101. data/lib/active_record/database_configurations/connection_url_resolver.rb +9 -2
  102. data/lib/active_record/database_configurations/database_config.rb +28 -5
  103. data/lib/active_record/database_configurations/hash_config.rb +103 -41
  104. data/lib/active_record/database_configurations/url_config.rb +30 -1
  105. data/lib/active_record/database_configurations.rb +8 -4
  106. data/lib/active_record/delegated_type.rb +43 -19
  107. data/lib/active_record/dynamic_matchers.rb +56 -71
  108. data/lib/active_record/encryption/config.rb +3 -1
  109. data/lib/active_record/encryption/encryptable_record.rb +12 -12
  110. data/lib/active_record/encryption/encrypted_attribute_type.rb +35 -6
  111. data/lib/active_record/encryption/encryptor.rb +58 -22
  112. data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -2
  113. data/lib/active_record/encryption/key_provider.rb +1 -1
  114. data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
  115. data/lib/active_record/encryption/message_serializer.rb +4 -0
  116. data/lib/active_record/encryption/null_encryptor.rb +4 -0
  117. data/lib/active_record/encryption/read_only_null_encryptor.rb +4 -0
  118. data/lib/active_record/encryption/scheme.rb +9 -2
  119. data/lib/active_record/enum.rb +57 -36
  120. data/lib/active_record/errors.rb +76 -26
  121. data/lib/active_record/explain.rb +14 -25
  122. data/lib/active_record/explain_registry.rb +51 -2
  123. data/lib/active_record/filter_attribute_handler.rb +73 -0
  124. data/lib/active_record/fixture_set/table_row.rb +19 -2
  125. data/lib/active_record/fixtures.rb +39 -35
  126. data/lib/active_record/future_result.rb +21 -13
  127. data/lib/active_record/gem_version.rb +3 -3
  128. data/lib/active_record/inheritance.rb +5 -3
  129. data/lib/active_record/insert_all.rb +28 -20
  130. data/lib/active_record/integration.rb +4 -1
  131. data/lib/active_record/internal_metadata.rb +48 -34
  132. data/lib/active_record/locking/optimistic.rb +15 -7
  133. data/lib/active_record/locking/pessimistic.rb +5 -0
  134. data/lib/active_record/log_subscriber.rb +3 -34
  135. data/lib/active_record/message_pack.rb +1 -1
  136. data/lib/active_record/middleware/shard_selector.rb +34 -17
  137. data/lib/active_record/migration/command_recorder.rb +46 -14
  138. data/lib/active_record/migration/compatibility.rb +40 -25
  139. data/lib/active_record/migration/default_schema_versions_formatter.rb +30 -0
  140. data/lib/active_record/migration/default_strategy.rb +4 -5
  141. data/lib/active_record/migration/pending_migration_connection.rb +2 -2
  142. data/lib/active_record/migration.rb +119 -103
  143. data/lib/active_record/model_schema.rb +66 -78
  144. data/lib/active_record/nested_attributes.rb +17 -9
  145. data/lib/active_record/persistence.rb +161 -454
  146. data/lib/active_record/query_cache.rb +33 -15
  147. data/lib/active_record/query_logs.rb +106 -39
  148. data/lib/active_record/query_logs_formatter.rb +17 -28
  149. data/lib/active_record/querying.rb +28 -16
  150. data/lib/active_record/railtie.rb +61 -74
  151. data/lib/active_record/railties/controller_runtime.rb +19 -5
  152. data/lib/active_record/railties/databases.rake +64 -78
  153. data/lib/active_record/railties/job_checkpoints.rb +15 -0
  154. data/lib/active_record/railties/job_runtime.rb +10 -11
  155. data/lib/active_record/reflection.rb +147 -53
  156. data/lib/active_record/relation/batches/batch_enumerator.rb +19 -5
  157. data/lib/active_record/relation/batches.rb +153 -73
  158. data/lib/active_record/relation/calculations.rb +146 -96
  159. data/lib/active_record/relation/delegation.rb +30 -23
  160. data/lib/active_record/relation/finder_methods.rb +64 -34
  161. data/lib/active_record/relation/merger.rb +12 -14
  162. data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
  163. data/lib/active_record/relation/predicate_builder/association_query_value.rb +19 -11
  164. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +8 -8
  165. data/lib/active_record/relation/predicate_builder/relation_handler.rb +4 -3
  166. data/lib/active_record/relation/predicate_builder.rb +25 -10
  167. data/lib/active_record/relation/query_attribute.rb +4 -2
  168. data/lib/active_record/relation/query_methods.rb +351 -124
  169. data/lib/active_record/relation/spawn_methods.rb +9 -25
  170. data/lib/active_record/relation/where_clause.rb +17 -30
  171. data/lib/active_record/relation.rb +590 -124
  172. data/lib/active_record/result.rb +131 -59
  173. data/lib/active_record/runtime_registry.rb +44 -21
  174. data/lib/active_record/sanitization.rb +33 -25
  175. data/lib/active_record/schema.rb +8 -6
  176. data/lib/active_record/schema_dumper.rb +66 -31
  177. data/lib/active_record/schema_migration.rb +31 -14
  178. data/lib/active_record/scoping/named.rb +6 -2
  179. data/lib/active_record/scoping.rb +0 -1
  180. data/lib/active_record/secure_token.rb +3 -3
  181. data/lib/active_record/signed_id.rb +68 -20
  182. data/lib/active_record/statement_cache.rb +29 -25
  183. data/lib/active_record/store.rb +51 -22
  184. data/lib/active_record/structured_event_subscriber.rb +85 -0
  185. data/lib/active_record/table_metadata.rb +7 -33
  186. data/lib/active_record/tasks/abstract_tasks.rb +76 -0
  187. data/lib/active_record/tasks/database_tasks.rb +118 -90
  188. data/lib/active_record/tasks/mysql_database_tasks.rb +3 -42
  189. data/lib/active_record/tasks/postgresql_database_tasks.rb +14 -40
  190. data/lib/active_record/tasks/sqlite_database_tasks.rb +17 -28
  191. data/lib/active_record/test_databases.rb +14 -4
  192. data/lib/active_record/test_fixtures.rb +123 -89
  193. data/lib/active_record/testing/query_assertions.rb +127 -0
  194. data/lib/active_record/timestamp.rb +6 -4
  195. data/lib/active_record/token_for.rb +22 -12
  196. data/lib/active_record/touch_later.rb +1 -1
  197. data/lib/active_record/transaction.rb +129 -0
  198. data/lib/active_record/transactions.rb +97 -18
  199. data/lib/active_record/translation.rb +0 -2
  200. data/lib/active_record/type/hash_lookup_type_map.rb +2 -1
  201. data/lib/active_record/type/internal/timezone.rb +7 -0
  202. data/lib/active_record/type/json.rb +15 -2
  203. data/lib/active_record/type/serialized.rb +12 -7
  204. data/lib/active_record/type/type_map.rb +1 -1
  205. data/lib/active_record/type_caster/connection.rb +5 -4
  206. data/lib/active_record/validations/associated.rb +10 -4
  207. data/lib/active_record/validations/uniqueness.rb +23 -18
  208. data/lib/active_record/validations.rb +4 -1
  209. data/lib/active_record.rb +203 -59
  210. data/lib/arel/alias_predication.rb +3 -1
  211. data/lib/arel/collectors/bind.rb +4 -2
  212. data/lib/arel/collectors/composite.rb +7 -0
  213. data/lib/arel/collectors/sql_string.rb +2 -2
  214. data/lib/arel/collectors/substitute_binds.rb +3 -3
  215. data/lib/arel/crud.rb +8 -11
  216. data/lib/arel/delete_manager.rb +5 -0
  217. data/lib/arel/nodes/binary.rb +1 -7
  218. data/lib/arel/nodes/bound_sql_literal.rb +9 -5
  219. data/lib/arel/nodes/count.rb +2 -2
  220. data/lib/arel/nodes/delete_statement.rb +4 -2
  221. data/lib/arel/nodes/function.rb +4 -10
  222. data/lib/arel/nodes/named_function.rb +2 -2
  223. data/lib/arel/nodes/{and.rb → nary.rb} +5 -2
  224. data/lib/arel/nodes/node.rb +6 -5
  225. data/lib/arel/nodes/sql_literal.rb +8 -1
  226. data/lib/arel/nodes/update_statement.rb +4 -2
  227. data/lib/arel/nodes.rb +2 -4
  228. data/lib/arel/predications.rb +1 -1
  229. data/lib/arel/select_manager.rb +14 -5
  230. data/lib/arel/table.rb +3 -7
  231. data/lib/arel/tree_manager.rb +3 -2
  232. data/lib/arel/update_manager.rb +7 -1
  233. data/lib/arel/visitors/dot.rb +3 -3
  234. data/lib/arel/visitors/mysql.rb +9 -4
  235. data/lib/arel/visitors/postgresql.rb +56 -12
  236. data/lib/arel/visitors/sqlite.rb +80 -8
  237. data/lib/arel/visitors/to_sql.rb +34 -37
  238. data/lib/arel.rb +10 -4
  239. data/lib/rails/generators/active_record/application_record/USAGE +1 -1
  240. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
  241. metadata +23 -14
  242. data/lib/active_record/explain_subscriber.rb +0 -34
  243. data/lib/active_record/normalization.rb +0 -167
  244. data/lib/active_record/relation/record_fetch_warning.rb +0 -49
@@ -48,7 +48,7 @@ module ActiveRecord
48
48
  # way of creating a namespace for tables in a shared database. By default, the prefix is the
49
49
  # empty string.
50
50
  #
51
- # If you are organising your models within modules you can add a prefix to the models within
51
+ # If you are organizing your models within modules you can add a prefix to the models within
52
52
  # a namespace by defining a singleton method in the parent module called table_name_prefix which
53
53
  # returns your chosen prefix.
54
54
 
@@ -65,7 +65,7 @@ module ActiveRecord
65
65
  # Works like +table_name_prefix=+, but appends instead of prepends (set to "_basecamp" gives "projects_basecamp",
66
66
  # "people_basecamp"). By default, the suffix is the empty string.
67
67
  #
68
- # If you are organising your models within modules, you can add a suffix to the models within
68
+ # If you are organizing your models within modules, you can add a suffix to the models within
69
69
  # a namespace by defining a singleton method in the parent module called table_name_suffix which
70
70
  # returns your chosen suffix.
71
71
 
@@ -113,17 +113,19 @@ module ActiveRecord
113
113
  # :singleton-method: implicit_order_column
114
114
  # :call-seq: implicit_order_column
115
115
  #
116
- # The name of the column records are ordered by if no explicit order clause
116
+ # The name of the column(s) records are ordered by if no explicit order clause
117
117
  # is used during an ordered finder call. If not set the primary key is used.
118
118
 
119
119
  ##
120
120
  # :singleton-method: implicit_order_column=
121
121
  # :call-seq: implicit_order_column=(column_name)
122
122
  #
123
- # Sets the column to sort records by when no explicit order clause is used
124
- # during an ordered finder call. Useful when the primary key is not an
125
- # auto-incrementing integer, for example when it's a UUID. Records are subsorted
126
- # by the primary key if it exists to ensure deterministic results.
123
+ # Sets the column(s) to sort records by when no explicit order clause is used
124
+ # during an ordered finder call. Useful for models where the primary key isn't an
125
+ # auto-incrementing integer (such as UUID).
126
+ #
127
+ # By default, records are subsorted by primary key to ensure deterministic results.
128
+ # To disable this subsort behavior, set `implicit_order_column` to `["column_name", nil]`.
127
129
 
128
130
  ##
129
131
  # :singleton-method: immutable_strings_by_default=
@@ -146,6 +148,11 @@ module ActiveRecord
146
148
  # your own model for something else, you can set +inheritance_column+:
147
149
  #
148
150
  # self.inheritance_column = 'zoink'
151
+ #
152
+ # If you wish to disable single-table inheritance altogether you can set
153
+ # +inheritance_column+ to +nil+
154
+ #
155
+ # self.inheritance_column = nil
149
156
 
150
157
  ##
151
158
  # :singleton-method: inheritance_column=
@@ -174,6 +181,7 @@ module ActiveRecord
174
181
  self.protected_environments = ["production"]
175
182
 
176
183
  self.ignored_columns = [].freeze
184
+ self.only_columns = [].freeze
177
185
 
178
186
  delegate :type_for_attribute, :column_for_attribute, to: :class
179
187
 
@@ -271,15 +279,14 @@ module ActiveRecord
271
279
  end
272
280
 
273
281
  @table_name = value
274
- @quoted_table_name = nil
275
282
  @arel_table = nil
276
- @sequence_name = nil unless defined?(@explicit_sequence_name) && @explicit_sequence_name
283
+ @sequence_name = nil unless @explicit_sequence_name
277
284
  @predicate_builder = nil
278
285
  end
279
286
 
280
- # Returns a quoted version of the table name, used to construct SQL statements.
287
+ # Returns a quoted version of the table name.
281
288
  def quoted_table_name
282
- @quoted_table_name ||= connection.quote_table_name(table_name)
289
+ adapter_class.quote_table_name(table_name)
283
290
  end
284
291
 
285
292
  # Computes the table name, (re)sets it internally, and returns it.
@@ -328,6 +335,12 @@ module ActiveRecord
328
335
  @ignored_columns || superclass.ignored_columns
329
336
  end
330
337
 
338
+ # The list of columns names the model should allow. Only columns are used to define
339
+ # attribute accessors, and are referenced in SQL queries.
340
+ def only_columns
341
+ @only_columns || superclass.only_columns
342
+ end
343
+
331
344
  # Sets the columns names the model should ignore. Ignored columns won't have attribute
332
345
  # accessors defined, and won't be referenced in SQL queries.
333
346
  #
@@ -360,10 +373,17 @@ module ActiveRecord
360
373
  # user = Project.create!(name: "First Project")
361
374
  # user.category # => raises NoMethodError
362
375
  def ignored_columns=(columns)
376
+ check_model_columns(@only_columns.present?)
363
377
  reload_schema_from_cache
364
378
  @ignored_columns = columns.map(&:to_s).freeze
365
379
  end
366
380
 
381
+ def only_columns=(columns)
382
+ check_model_columns(@ignored_columns.present?)
383
+ reload_schema_from_cache
384
+ @only_columns = columns.map(&:to_s).freeze
385
+ end
386
+
367
387
  def sequence_name
368
388
  if base_class?
369
389
  @sequence_name ||= reset_sequence_name
@@ -374,7 +394,7 @@ module ActiveRecord
374
394
 
375
395
  def reset_sequence_name # :nodoc:
376
396
  @explicit_sequence_name = false
377
- @sequence_name = connection.default_sequence_name(table_name, primary_key)
397
+ @sequence_name = with_connection { |c| c.default_sequence_name(table_name, primary_key) }
378
398
  end
379
399
 
380
400
  # Sets the name of the sequence to use when generating ids to the given
@@ -399,39 +419,37 @@ module ActiveRecord
399
419
  # Determines if the primary key values should be selected from their
400
420
  # corresponding sequence before the insert statement.
401
421
  def prefetch_primary_key?
402
- connection.prefetch_primary_key?(table_name)
422
+ with_connection { |c| c.prefetch_primary_key?(table_name) }
403
423
  end
404
424
 
405
425
  # Returns the next value that will be used as the primary key on
406
426
  # an insert statement.
407
427
  def next_sequence_value
408
- connection.next_sequence_value(sequence_name)
428
+ with_connection { |c| c.next_sequence_value(sequence_name) }
409
429
  end
410
430
 
411
431
  # Indicates whether the table associated with this class exists
412
432
  def table_exists?
413
- connection.schema_cache.data_source_exists?(table_name)
433
+ schema_cache.data_source_exists?(table_name)
414
434
  end
415
435
 
416
436
  def attributes_builder # :nodoc:
417
- unless defined?(@attributes_builder) && @attributes_builder
437
+ @attributes_builder ||= begin
418
438
  defaults = _default_attributes.except(*(column_names - [primary_key]))
419
- @attributes_builder = ActiveModel::AttributeSet::Builder.new(attribute_types, defaults)
439
+ ActiveModel::AttributeSet::Builder.new(attribute_types, defaults)
420
440
  end
421
- @attributes_builder
422
441
  end
423
442
 
424
443
  def columns_hash # :nodoc:
425
- load_schema
444
+ load_schema unless @columns_hash
426
445
  @columns_hash
427
446
  end
428
447
 
429
448
  def columns
430
- load_schema
431
449
  @columns ||= columns_hash.values.freeze
432
450
  end
433
451
 
434
- def _returning_columns_for_insert # :nodoc:
452
+ def _returning_columns_for_insert(connection) # :nodoc:
435
453
  @_returning_columns_for_insert ||= begin
436
454
  auto_populated_columns = columns.filter_map do |c|
437
455
  c.name if connection.return_value_after_insert?(c)
@@ -441,37 +459,10 @@ module ActiveRecord
441
459
  end
442
460
  end
443
461
 
444
- def attribute_types # :nodoc:
445
- load_schema
446
- @attribute_types ||= Hash.new(Type.default_value)
447
- end
448
-
449
462
  def yaml_encoder # :nodoc:
450
463
  @yaml_encoder ||= ActiveModel::AttributeSet::YAMLEncoder.new(attribute_types)
451
464
  end
452
465
 
453
- # Returns the type of the attribute with the given name, after applying
454
- # all modifiers. This method is the only valid source of information for
455
- # anything related to the types of a model's attributes. This method will
456
- # access the database and load the model's schema if it is required.
457
- #
458
- # The return value of this method will implement the interface described
459
- # by ActiveModel::Type::Value (though the object itself may not subclass
460
- # it).
461
- #
462
- # +attr_name+ The name of the attribute to retrieve the type for. Must be
463
- # a string or a symbol.
464
- def type_for_attribute(attr_name, &block)
465
- attr_name = attr_name.to_s
466
- attr_name = attribute_aliases[attr_name] || attr_name
467
-
468
- if block
469
- attribute_types.fetch(attr_name, &block)
470
- else
471
- attribute_types[attr_name]
472
- end
473
- end
474
-
475
466
  # Returns the column object for the named attribute.
476
467
  # Returns an ActiveRecord::ConnectionAdapters::NullColumn if the
477
468
  # named attribute does not exist.
@@ -499,11 +490,6 @@ module ActiveRecord
499
490
  @column_defaults ||= _default_attributes.deep_dup.to_hash.freeze
500
491
  end
501
492
 
502
- def _default_attributes # :nodoc:
503
- load_schema
504
- @default_attributes ||= ActiveModel::AttributeSet.new({})
505
- end
506
-
507
493
  # Returns an array of column names as strings.
508
494
  def column_names
509
495
  @column_names ||= columns.map(&:name).freeze
@@ -531,7 +517,7 @@ module ActiveRecord
531
517
  # when just after creating a table you want to populate it with some default
532
518
  # values, e.g.:
533
519
  #
534
- # class CreateJobLevels < ActiveRecord::Migration[7.1]
520
+ # class CreateJobLevels < ActiveRecord::Migration[8.1]
535
521
  # def up
536
522
  # create_table :job_levels do |t|
537
523
  # t.integer :id
@@ -551,18 +537,20 @@ module ActiveRecord
551
537
  # end
552
538
  # end
553
539
  def reset_column_information
554
- connection.clear_cache!
540
+ connection_pool.active_connection&.clear_cache!
555
541
  ([self] + descendants).each(&:undefine_attribute_methods)
556
- connection.schema_cache.clear_data_source_cache!(table_name)
542
+ schema_cache.clear_data_source_cache!(table_name)
557
543
 
558
544
  reload_schema_from_cache
559
545
  initialize_find_by_cache
560
546
  end
561
547
 
562
- def load_schema # :nodoc:
548
+ # Load the model's schema information either from the schema cache
549
+ # or directly from the database.
550
+ def load_schema
563
551
  return if schema_loaded?
564
552
  @load_schema_monitor.synchronize do
565
- return if @columns_hash
553
+ return if schema_loaded?
566
554
 
567
555
  load_schema!
568
556
 
@@ -583,9 +571,7 @@ module ActiveRecord
583
571
  @arel_table = nil
584
572
  @column_names = nil
585
573
  @symbol_column_to_string_name_hash = nil
586
- @attribute_types = nil
587
574
  @content_columns = nil
588
- @default_attributes = nil
589
575
  @column_defaults = nil
590
576
  @attributes_builder = nil
591
577
  @columns = nil
@@ -607,11 +593,12 @@ module ActiveRecord
607
593
  child_class.reload_schema_from_cache(false)
608
594
  child_class.class_eval do
609
595
  @ignored_columns = nil
596
+ @only_columns = nil
610
597
  end
611
598
  end
612
599
 
613
600
  def schema_loaded?
614
- defined?(@schema_loaded) && @schema_loaded
601
+ @schema_loaded
615
602
  end
616
603
 
617
604
  def load_schema!
@@ -619,20 +606,14 @@ module ActiveRecord
619
606
  raise ActiveRecord::TableNotSpecified, "#{self} has no table configured. Set one with #{self}.table_name="
620
607
  end
621
608
 
622
- columns_hash = connection.schema_cache.columns_hash(table_name)
623
- columns_hash = columns_hash.except(*ignored_columns) unless ignored_columns.empty?
624
- @columns_hash = columns_hash.freeze
625
- @columns_hash.each do |name, column|
626
- type = connection.lookup_cast_type_from_column(column)
627
- type = _convert_type_from_options(type)
628
- define_attribute(
629
- name,
630
- type,
631
- default: column.default,
632
- user_provided_default: false
633
- )
634
- alias_attribute :id_value, :id if name == "id"
609
+ columns_hash = schema_cache.columns_hash(table_name)
610
+ if only_columns.present?
611
+ columns_hash = columns_hash.slice(*only_columns)
612
+ elsif ignored_columns.present?
613
+ columns_hash = columns_hash.except(*ignored_columns)
635
614
  end
615
+ @columns_hash = columns_hash.freeze
616
+
636
617
  _default_attributes # Precompute to cache DB-dependent attribute types
637
618
  end
638
619
 
@@ -659,12 +640,19 @@ module ActiveRecord
659
640
  end
660
641
  end
661
642
 
662
- def _convert_type_from_options(type)
643
+ def type_for_column(connection, column)
644
+ # TODO: Remove the need for a connection after we release 8.1.
645
+ type = column.fetch_cast_type(connection)
646
+
663
647
  if immutable_strings_by_default && type.respond_to?(:to_immutable_string)
664
- type.to_immutable_string
665
- else
666
- type
648
+ type = type.to_immutable_string
667
649
  end
650
+
651
+ type
652
+ end
653
+
654
+ def check_model_columns(columns_present)
655
+ raise ArgumentError, "You can not use both only_columns and ignored_columns in the same model." if columns_present
668
656
  end
669
657
  end
670
658
  end
@@ -387,6 +387,8 @@ module ActiveRecord
387
387
  generated_association_methods.module_eval <<-eoruby, __FILE__, __LINE__ + 1
388
388
  silence_redefinition_of_method :#{association_name}_attributes=
389
389
  def #{association_name}_attributes=(attributes)
390
+ association = association(:#{association_name})
391
+ deprecated_associations_api_guard(association, __method__)
390
392
  assign_nested_attributes_for_#{type}_association(:#{association_name}, attributes)
391
393
  end
392
394
  eoruby
@@ -421,10 +423,15 @@ module ActiveRecord
421
423
  # update_only is true, and a <tt>:_destroy</tt> key set to a truthy value,
422
424
  # then the existing record will be marked for destruction.
423
425
  def assign_nested_attributes_for_one_to_one_association(association_name, attributes)
424
- options = nested_attributes_options[association_name]
425
426
  if attributes.respond_to?(:permitted?)
426
427
  attributes = attributes.to_h
427
428
  end
429
+
430
+ unless attributes.is_a?(Hash)
431
+ raise ArgumentError, "Hash expected for `#{association_name}` attributes, got #{attributes.class.name}"
432
+ end
433
+
434
+ options = nested_attributes_options[association_name]
428
435
  attributes = attributes.with_indifferent_access
429
436
  existing_record = send(association_name)
430
437
 
@@ -486,7 +493,7 @@ module ActiveRecord
486
493
  end
487
494
 
488
495
  unless attributes_collection.is_a?(Hash) || attributes_collection.is_a?(Array)
489
- raise ArgumentError, "Hash or Array expected for attribute `#{association_name}`, got #{attributes_collection.class.name} (#{attributes_collection.inspect})"
496
+ raise ArgumentError, "Hash or Array expected for `#{association_name}` attributes, got #{attributes_collection.class.name}"
490
497
  end
491
498
 
492
499
  check_record_limit!(options[:limit], attributes_collection)
@@ -509,7 +516,7 @@ module ActiveRecord
509
516
  attribute_ids.empty? ? [] : association.scope.where(association.klass.primary_key => attribute_ids)
510
517
  end
511
518
 
512
- attributes_collection.each do |attributes|
519
+ records = attributes_collection.map do |attributes|
513
520
  if attributes.respond_to?(:permitted?)
514
521
  attributes = attributes.to_h
515
522
  end
@@ -519,12 +526,12 @@ module ActiveRecord
519
526
  unless reject_new_record?(association_name, attributes)
520
527
  association.reader.build(attributes.except(*UNASSIGNABLE_KEYS))
521
528
  end
522
- elsif existing_record = find_record_by_id(existing_records, attributes["id"])
529
+ elsif existing_record = find_record_by_id(association.klass, existing_records, attributes["id"])
523
530
  unless call_reject_if(association_name, attributes)
524
531
  # Make sure we are operating on the actual object which is in the association's
525
532
  # proxy_target array (either by finding it, or adding it if not found)
526
533
  # Take into account that the proxy_target may have changed due to callbacks
527
- target_record = find_record_by_id(association.target, attributes["id"])
534
+ target_record = find_record_by_id(association.klass, association.target, attributes["id"])
528
535
  if target_record
529
536
  existing_record = target_record
530
537
  else
@@ -532,11 +539,14 @@ module ActiveRecord
532
539
  end
533
540
 
534
541
  assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy])
542
+ existing_record
535
543
  end
536
544
  else
537
545
  raise_nested_attributes_record_not_found!(association_name, attributes["id"])
538
546
  end
539
547
  end
548
+
549
+ association.nested_attributes_target = records
540
550
  end
541
551
 
542
552
  # Takes in a limit and checks if the attributes_collection has too many
@@ -613,10 +623,8 @@ module ActiveRecord
613
623
  model, "id", record_id)
614
624
  end
615
625
 
616
- def find_record_by_id(records, id)
617
- return if records.empty?
618
-
619
- if records.first.class.composite_primary_key?
626
+ def find_record_by_id(klass, records, id)
627
+ if klass.composite_primary_key?
620
628
  id = Array(id).map(&:to_s)
621
629
  records.find { |record| Array(record.id).map(&:to_s) == id }
622
630
  else