activerecord 7.2.3.1 → 8.0.5.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 (132) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +475 -946
  3. data/README.rdoc +1 -1
  4. data/lib/active_record/association_relation.rb +1 -0
  5. data/lib/active_record/associations/association.rb +34 -10
  6. data/lib/active_record/associations/builder/association.rb +7 -6
  7. data/lib/active_record/associations/collection_association.rb +1 -1
  8. data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
  9. data/lib/active_record/associations/has_many_through_association.rb +3 -2
  10. data/lib/active_record/associations/join_dependency.rb +2 -2
  11. data/lib/active_record/associations/preloader/association.rb +2 -2
  12. data/lib/active_record/associations/preloader/batch.rb +7 -1
  13. data/lib/active_record/associations/singular_association.rb +8 -3
  14. data/lib/active_record/associations.rb +34 -4
  15. data/lib/active_record/asynchronous_queries_tracker.rb +28 -24
  16. data/lib/active_record/attribute_methods/primary_key.rb +4 -8
  17. data/lib/active_record/attribute_methods/query.rb +34 -0
  18. data/lib/active_record/attribute_methods/time_zone_conversion.rb +2 -12
  19. data/lib/active_record/autosave_association.rb +69 -27
  20. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +34 -25
  21. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +0 -1
  22. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +0 -1
  23. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +8 -17
  24. data/lib/active_record/connection_adapters/abstract/database_statements.rb +91 -44
  25. data/lib/active_record/connection_adapters/abstract/query_cache.rb +8 -2
  26. data/lib/active_record/connection_adapters/abstract/quoting.rb +1 -1
  27. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +4 -5
  28. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +7 -2
  29. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +37 -10
  30. data/lib/active_record/connection_adapters/abstract/transaction.rb +15 -5
  31. data/lib/active_record/connection_adapters/abstract_adapter.rb +67 -74
  32. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +21 -40
  33. data/lib/active_record/connection_adapters/mysql/quoting.rb +0 -8
  34. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +2 -8
  35. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +50 -45
  36. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +84 -94
  37. data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -8
  38. data/lib/active_record/connection_adapters/pool_config.rb +7 -7
  39. data/lib/active_record/connection_adapters/postgresql/column.rb +4 -2
  40. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +72 -43
  41. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
  42. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +10 -0
  43. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -4
  44. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +1 -11
  45. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +6 -12
  46. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +2 -1
  47. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +59 -16
  48. data/lib/active_record/connection_adapters/postgresql_adapter.rb +53 -96
  49. data/lib/active_record/connection_adapters/schema_cache.rb +1 -3
  50. data/lib/active_record/connection_adapters/sqlite3/column.rb +8 -2
  51. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +80 -100
  52. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +0 -6
  53. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +27 -2
  54. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +9 -1
  55. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +53 -12
  56. data/lib/active_record/connection_adapters/statement_pool.rb +4 -2
  57. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +37 -67
  58. data/lib/active_record/connection_adapters/trilogy_adapter.rb +0 -17
  59. data/lib/active_record/connection_adapters.rb +0 -56
  60. data/lib/active_record/connection_handling.rb +23 -1
  61. data/lib/active_record/core.rb +29 -14
  62. data/lib/active_record/database_configurations/database_config.rb +4 -0
  63. data/lib/active_record/database_configurations/hash_config.rb +16 -2
  64. data/lib/active_record/encryption/config.rb +3 -1
  65. data/lib/active_record/encryption/encryptable_record.rb +4 -4
  66. data/lib/active_record/encryption/encrypted_attribute_type.rb +10 -1
  67. data/lib/active_record/encryption/encryptor.rb +16 -8
  68. data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -2
  69. data/lib/active_record/encryption/scheme.rb +8 -1
  70. data/lib/active_record/enum.rb +9 -22
  71. data/lib/active_record/errors.rb +13 -5
  72. data/lib/active_record/fixtures.rb +0 -2
  73. data/lib/active_record/future_result.rb +15 -9
  74. data/lib/active_record/gem_version.rb +3 -3
  75. data/lib/active_record/insert_all.rb +3 -3
  76. data/lib/active_record/locking/optimistic.rb +1 -1
  77. data/lib/active_record/log_subscriber.rb +5 -11
  78. data/lib/active_record/migration/command_recorder.rb +32 -12
  79. data/lib/active_record/migration/compatibility.rb +5 -2
  80. data/lib/active_record/migration.rb +38 -42
  81. data/lib/active_record/model_schema.rb +3 -4
  82. data/lib/active_record/nested_attributes.rb +4 -6
  83. data/lib/active_record/persistence.rb +128 -130
  84. data/lib/active_record/query_logs.rb +102 -50
  85. data/lib/active_record/query_logs_formatter.rb +17 -28
  86. data/lib/active_record/querying.rb +8 -8
  87. data/lib/active_record/railtie.rb +2 -26
  88. data/lib/active_record/railties/databases.rake +11 -35
  89. data/lib/active_record/reflection.rb +18 -21
  90. data/lib/active_record/relation/batches/batch_enumerator.rb +4 -3
  91. data/lib/active_record/relation/batches.rb +132 -72
  92. data/lib/active_record/relation/calculations.rb +40 -39
  93. data/lib/active_record/relation/delegation.rb +25 -14
  94. data/lib/active_record/relation/finder_methods.rb +18 -18
  95. data/lib/active_record/relation/merger.rb +8 -8
  96. data/lib/active_record/relation/predicate_builder/array_handler.rb +3 -1
  97. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -1
  98. data/lib/active_record/relation/predicate_builder/relation_handler.rb +4 -3
  99. data/lib/active_record/relation/predicate_builder.rb +13 -0
  100. data/lib/active_record/relation/query_methods.rb +105 -61
  101. data/lib/active_record/relation/spawn_methods.rb +7 -7
  102. data/lib/active_record/relation/where_clause.rb +1 -1
  103. data/lib/active_record/relation.rb +80 -62
  104. data/lib/active_record/result.rb +66 -4
  105. data/lib/active_record/sanitization.rb +7 -6
  106. data/lib/active_record/schema_dumper.rb +5 -0
  107. data/lib/active_record/schema_migration.rb +2 -1
  108. data/lib/active_record/scoping/named.rb +5 -2
  109. data/lib/active_record/statement_cache.rb +14 -14
  110. data/lib/active_record/store.rb +7 -3
  111. data/lib/active_record/table_metadata.rb +1 -3
  112. data/lib/active_record/tasks/database_tasks.rb +69 -60
  113. data/lib/active_record/tasks/mysql_database_tasks.rb +0 -2
  114. data/lib/active_record/tasks/postgresql_database_tasks.rb +2 -1
  115. data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -2
  116. data/lib/active_record/test_databases.rb +1 -1
  117. data/lib/active_record/test_fixtures.rb +12 -0
  118. data/lib/active_record/token_for.rb +1 -1
  119. data/lib/active_record/transactions.rb +5 -6
  120. data/lib/active_record/type/serialized.rb +5 -0
  121. data/lib/active_record/validations/uniqueness.rb +8 -8
  122. data/lib/active_record.rb +21 -48
  123. data/lib/arel/collectors/bind.rb +2 -2
  124. data/lib/arel/collectors/sql_string.rb +1 -1
  125. data/lib/arel/collectors/substitute_binds.rb +2 -2
  126. data/lib/arel/nodes/binary.rb +1 -1
  127. data/lib/arel/nodes/node.rb +1 -1
  128. data/lib/arel/nodes/sql_literal.rb +1 -1
  129. data/lib/arel/predications.rb +1 -3
  130. data/lib/arel/table.rb +3 -7
  131. metadata +10 -11
  132. data/lib/active_record/relation/record_fetch_warning.rb +0 -52
@@ -22,10 +22,12 @@ module ActiveRecord
22
22
  # * change_table_comment (must supply a +:from+ and +:to+ option)
23
23
  # * create_enum
24
24
  # * create_join_table
25
+ # * create_virtual_table
25
26
  # * create_table
26
27
  # * disable_extension
27
28
  # * drop_enum (must supply a list of values)
28
29
  # * drop_join_table
30
+ # * drop_virtual_table (must supply options)
29
31
  # * drop_table (must supply a block)
30
32
  # * enable_extension
31
33
  # * remove_column (must supply a type)
@@ -38,7 +40,7 @@ module ActiveRecord
38
40
  # * remove_reference
39
41
  # * remove_timestamps
40
42
  # * rename_column
41
- # * rename_enum (must supply a +:to+ option)
43
+ # * rename_enum
42
44
  # * rename_enum_value (must supply a +:from+ and +:to+ option)
43
45
  # * rename_index
44
46
  # * rename_table
@@ -55,6 +57,8 @@ module ActiveRecord
55
57
  :add_exclusion_constraint, :remove_exclusion_constraint,
56
58
  :add_unique_constraint, :remove_unique_constraint,
57
59
  :create_enum, :drop_enum, :rename_enum, :add_enum_value, :rename_enum_value,
60
+ :create_schema, :drop_schema,
61
+ :create_virtual_table, :drop_virtual_table
58
62
  ]
59
63
  include JoinTable
60
64
 
@@ -135,7 +139,7 @@ module ActiveRecord
135
139
  recorder.reverting = @reverting
136
140
  yield recorder.delegate.update_table_definition(table_name, recorder)
137
141
  commands = recorder.commands
138
- @commands << [:change_table, [table_name], -> t { bulk_change_table(table_name, commands) }]
142
+ @commands << [:change_table, [table_name], -> t { bulk_change_table(t.name, commands.reverse) }]
139
143
  else
140
144
  yield delegate.update_table_definition(table_name, self)
141
145
  end
@@ -163,7 +167,9 @@ module ActiveRecord
163
167
  add_exclusion_constraint: :remove_exclusion_constraint,
164
168
  add_unique_constraint: :remove_unique_constraint,
165
169
  enable_extension: :disable_extension,
166
- create_enum: :drop_enum
170
+ create_enum: :drop_enum,
171
+ create_schema: :drop_schema,
172
+ create_virtual_table: :drop_virtual_table
167
173
  }.each do |cmd, inv|
168
174
  [[inv, cmd], [cmd, inv]].uniq.each do |method, inverse|
169
175
  class_eval <<-EOV, __FILE__, __LINE__ + 1
@@ -196,13 +202,20 @@ module ActiveRecord
196
202
  end
197
203
 
198
204
  def invert_drop_table(args, &block)
199
- if args.last.is_a?(Hash)
200
- args.last.delete(:if_exists)
205
+ options = args.extract_options!
206
+ options.delete(:if_exists)
207
+
208
+ if args.size > 1
209
+ raise ActiveRecord::IrreversibleMigration, "To avoid mistakes, drop_table is only reversible if given a single table name."
201
210
  end
202
- if args.size == 1 && block == nil
211
+
212
+ if args.size == 1 && options == {} && block == nil
203
213
  raise ActiveRecord::IrreversibleMigration, "To avoid mistakes, drop_table is only reversible if given options or a block (can be empty)."
204
214
  end
205
- super
215
+
216
+ args << options unless options.empty?
217
+
218
+ super(args, &block)
206
219
  end
207
220
 
208
221
  def invert_rename_table(args)
@@ -353,13 +366,13 @@ module ActiveRecord
353
366
  end
354
367
 
355
368
  def invert_rename_enum(args)
356
- name, options = args
369
+ name, new_name, = args
357
370
 
358
- unless options.is_a?(Hash) && options.has_key?(:to)
359
- raise ActiveRecord::IrreversibleMigration, "rename_enum is only reversible if given a :to option."
371
+ if new_name.is_a?(Hash) && new_name.key?(:to)
372
+ new_name = new_name[:to]
360
373
  end
361
374
 
362
- [:rename_enum, [options[:to], to: name]]
375
+ [:rename_enum, [new_name, name]]
363
376
  end
364
377
 
365
378
  def invert_rename_enum_value(args)
@@ -369,7 +382,14 @@ module ActiveRecord
369
382
  raise ActiveRecord::IrreversibleMigration, "rename_enum_value is only reversible if given a :from and :to option."
370
383
  end
371
384
 
372
- [:rename_enum_value, [type_name, from: options[:to], to: options[:from]]]
385
+ options[:to], options[:from] = options[:from], options[:to]
386
+ [:rename_enum_value, [type_name, options]]
387
+ end
388
+
389
+ def invert_drop_virtual_table(args)
390
+ _enum, values = args.dup.tap(&:extract_options!)
391
+ raise ActiveRecord::IrreversibleMigration, "drop_virtual_table is only reversible if given options." unless values
392
+ super
373
393
  end
374
394
 
375
395
  def respond_to_missing?(method, _)
@@ -21,7 +21,7 @@ module ActiveRecord
21
21
  # New migration functionality that will never be backward compatible should be added directly to `ActiveRecord::Migration`.
22
22
  #
23
23
  # There are classes for each prior Rails version. Each class descends from the *next* Rails version, so:
24
- # 5.2 < 6.0 < 6.1 < 7.0 < 7.1 < 7.2
24
+ # 5.2 < 6.0 < 6.1 < 7.0 < 7.1 < 7.2 < 8.0
25
25
  #
26
26
  # If you are introducing new migration functionality that should only apply from Rails 7 onward, then you should
27
27
  # find the class that immediately precedes it (6.1), and override the relevant migration methods to undo your changes.
@@ -29,7 +29,10 @@ module ActiveRecord
29
29
  # For example, Rails 6 added a default value for the `precision` option on datetime columns. So in this file, the `V5_2`
30
30
  # class sets the value of `precision` to `nil` if it's not explicitly provided. This way, the default value will not apply
31
31
  # for migrations written for 5.2, but will for migrations written for 6.0.
32
- V7_2 = Current
32
+ V8_0 = Current
33
+
34
+ class V7_2 < V8_0
35
+ end
33
36
 
34
37
  class V7_1 < V7_2
35
38
  end
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "benchmark"
4
- require "set"
5
- require "zlib"
6
3
  require "active_support/core_ext/array/access"
7
4
  require "active_support/core_ext/enumerable"
8
5
  require "active_support/core_ext/module/attribute_accessors"
@@ -21,7 +18,7 @@ module ActiveRecord
21
18
  # For example the following migration is not reversible.
22
19
  # Rolling back this migration will raise an ActiveRecord::IrreversibleMigration error.
23
20
  #
24
- # class IrreversibleMigrationExample < ActiveRecord::Migration[7.2]
21
+ # class IrreversibleMigrationExample < ActiveRecord::Migration[8.0]
25
22
  # def change
26
23
  # create_table :distributors do |t|
27
24
  # t.string :zipcode
@@ -39,7 +36,7 @@ module ActiveRecord
39
36
  #
40
37
  # 1. Define <tt>#up</tt> and <tt>#down</tt> methods instead of <tt>#change</tt>:
41
38
  #
42
- # class ReversibleMigrationExample < ActiveRecord::Migration[7.2]
39
+ # class ReversibleMigrationExample < ActiveRecord::Migration[8.0]
43
40
  # def up
44
41
  # create_table :distributors do |t|
45
42
  # t.string :zipcode
@@ -64,7 +61,7 @@ module ActiveRecord
64
61
  #
65
62
  # 2. Use the #reversible method in <tt>#change</tt> method:
66
63
  #
67
- # class ReversibleMigrationExample < ActiveRecord::Migration[7.2]
64
+ # class ReversibleMigrationExample < ActiveRecord::Migration[8.0]
68
65
  # def change
69
66
  # create_table :distributors do |t|
70
67
  # t.string :zipcode
@@ -151,11 +148,10 @@ module ActiveRecord
151
148
  include ActiveSupport::ActionableError
152
149
 
153
150
  action "Run pending migrations" do
154
- ActiveRecord::Tasks::DatabaseTasks.migrate
151
+ ActiveRecord::Tasks::DatabaseTasks.migrate_all
155
152
 
156
153
  if ActiveRecord.dump_schema_after_migration
157
- connection = ActiveRecord::Tasks::DatabaseTasks.migration_connection
158
- ActiveRecord::Tasks::DatabaseTasks.dump_schema(connection.pool.db_config)
154
+ ActiveRecord::Tasks::DatabaseTasks.dump_all
159
155
  end
160
156
  end
161
157
 
@@ -250,7 +246,7 @@ module ActiveRecord
250
246
  #
251
247
  # Example of a simple migration:
252
248
  #
253
- # class AddSsl < ActiveRecord::Migration[7.2]
249
+ # class AddSsl < ActiveRecord::Migration[8.0]
254
250
  # def up
255
251
  # add_column :accounts, :ssl_enabled, :boolean, default: true
256
252
  # end
@@ -270,7 +266,7 @@ module ActiveRecord
270
266
  #
271
267
  # Example of a more complex migration that also needs to initialize data:
272
268
  #
273
- # class AddSystemSettings < ActiveRecord::Migration[7.2]
269
+ # class AddSystemSettings < ActiveRecord::Migration[8.0]
274
270
  # def up
275
271
  # create_table :system_settings do |t|
276
272
  # t.string :name
@@ -357,7 +353,7 @@ module ActiveRecord
357
353
  #
358
354
  # === Deletion
359
355
  #
360
- # * <tt>drop_table(name)</tt>: Drops the table called +name+.
356
+ # * <tt>drop_table(*names)</tt>: Drops the given tables.
361
357
  # * <tt>drop_join_table(table_1, table_2, options)</tt>: Drops the join table
362
358
  # specified by the given arguments.
363
359
  # * <tt>remove_column(table_name, column_name, type, options)</tt>: Removes the column
@@ -399,7 +395,7 @@ module ActiveRecord
399
395
  # $ bin/rails generate migration add_fieldname_to_tablename fieldname:string
400
396
  #
401
397
  # This will generate the file <tt>timestamp_add_fieldname_to_tablename.rb</tt>, which will look like this:
402
- # class AddFieldnameToTablename < ActiveRecord::Migration[7.2]
398
+ # class AddFieldnameToTablename < ActiveRecord::Migration[8.0]
403
399
  # def change
404
400
  # add_column :tablenames, :fieldname, :string
405
401
  # end
@@ -425,7 +421,7 @@ module ActiveRecord
425
421
  #
426
422
  # Not all migrations change the schema. Some just fix the data:
427
423
  #
428
- # class RemoveEmptyTags < ActiveRecord::Migration[7.2]
424
+ # class RemoveEmptyTags < ActiveRecord::Migration[8.0]
429
425
  # def up
430
426
  # Tag.all.each { |tag| tag.destroy if tag.pages.empty? }
431
427
  # end
@@ -438,7 +434,7 @@ module ActiveRecord
438
434
  #
439
435
  # Others remove columns when they migrate up instead of down:
440
436
  #
441
- # class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[7.2]
437
+ # class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[8.0]
442
438
  # def up
443
439
  # remove_column :items, :incomplete_items_count
444
440
  # remove_column :items, :completed_items_count
@@ -452,7 +448,7 @@ module ActiveRecord
452
448
  #
453
449
  # And sometimes you need to do something in SQL not abstracted directly by migrations:
454
450
  #
455
- # class MakeJoinUnique < ActiveRecord::Migration[7.2]
451
+ # class MakeJoinUnique < ActiveRecord::Migration[8.0]
456
452
  # def up
457
453
  # execute "ALTER TABLE `pages_linked_pages` ADD UNIQUE `page_id_linked_page_id` (`page_id`,`linked_page_id`)"
458
454
  # end
@@ -469,7 +465,7 @@ module ActiveRecord
469
465
  # <tt>Base#reset_column_information</tt> in order to ensure that the model has the
470
466
  # latest column data from after the new column was added. Example:
471
467
  #
472
- # class AddPeopleSalary < ActiveRecord::Migration[7.2]
468
+ # class AddPeopleSalary < ActiveRecord::Migration[8.0]
473
469
  # def up
474
470
  # add_column :people, :salary, :integer
475
471
  # Person.reset_column_information
@@ -531,7 +527,7 @@ module ActiveRecord
531
527
  # To define a reversible migration, define the +change+ method in your
532
528
  # migration like this:
533
529
  #
534
- # class TenderloveMigration < ActiveRecord::Migration[7.2]
530
+ # class TenderloveMigration < ActiveRecord::Migration[8.0]
535
531
  # def change
536
532
  # create_table(:horses) do |t|
537
533
  # t.column :content, :text
@@ -561,7 +557,7 @@ module ActiveRecord
561
557
  # can't execute inside a transaction though, and for these situations
562
558
  # you can turn the automatic transactions off.
563
559
  #
564
- # class ChangeEnum < ActiveRecord::Migration[7.2]
560
+ # class ChangeEnum < ActiveRecord::Migration[8.0]
565
561
  # disable_ddl_transaction!
566
562
  #
567
563
  # def up
@@ -604,7 +600,7 @@ module ActiveRecord
604
600
  end
605
601
  end
606
602
 
607
- def drop_table(table_name, **options)
603
+ def drop_table(*table_names, **options)
608
604
  if block_given?
609
605
  super { |t| yield compatible_table_definition(t) }
610
606
  else
@@ -681,10 +677,6 @@ module ActiveRecord
681
677
  paths = all_configs.flat_map { |config| config.migrations_paths || Migrator.migrations_paths }.uniq
682
678
  @file_watcher.new([], paths.index_with(["rb"]), &block)
683
679
  end
684
-
685
- def connection
686
- ActiveRecord::Tasks::DatabaseTasks.migration_connection
687
- end
688
680
  end
689
681
 
690
682
  class << self
@@ -715,13 +707,7 @@ module ActiveRecord
715
707
 
716
708
  def load_schema_if_pending!
717
709
  if any_schema_needs_update?
718
- # Roundtrip to Rake to allow plugins to hook into database initialization.
719
- root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
720
-
721
- FileUtils.cd(root) do
722
- Base.connection_handler.clear_all_connections!(:all)
723
- system("bin/rails db:test:prepare")
724
- end
710
+ load_schema!
725
711
  end
726
712
 
727
713
  check_pending_migrations
@@ -760,7 +746,7 @@ module ActiveRecord
760
746
  private
761
747
  def any_schema_needs_update?
762
748
  !db_configs_in_current_env.all? do |db_config|
763
- Tasks::DatabaseTasks.schema_up_to_date?(db_config, ActiveRecord.schema_format)
749
+ Tasks::DatabaseTasks.schema_up_to_date?(db_config)
764
750
  end
765
751
  end
766
752
 
@@ -785,6 +771,16 @@ module ActiveRecord
785
771
  def env
786
772
  ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
787
773
  end
774
+
775
+ def load_schema!
776
+ # Roundtrip to Rake to allow plugins to hook into database initialization.
777
+ root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
778
+
779
+ FileUtils.cd(root) do
780
+ Base.connection_handler.clear_all_connections!(:all)
781
+ system("bin/rails db:test:prepare")
782
+ end
783
+ end
788
784
  end
789
785
 
790
786
  def disable_ddl_transaction # :nodoc:
@@ -822,7 +818,7 @@ module ActiveRecord
822
818
  # and create the table 'apples' on the way up, and the reverse
823
819
  # on the way down.
824
820
  #
825
- # class FixTLMigration < ActiveRecord::Migration[7.2]
821
+ # class FixTLMigration < ActiveRecord::Migration[8.0]
826
822
  # def change
827
823
  # revert do
828
824
  # create_table(:horses) do |t|
@@ -841,7 +837,7 @@ module ActiveRecord
841
837
  #
842
838
  # require_relative "20121212123456_tenderlove_migration"
843
839
  #
844
- # class FixupTLMigration < ActiveRecord::Migration[7.2]
840
+ # class FixupTLMigration < ActiveRecord::Migration[8.0]
845
841
  # def change
846
842
  # revert TenderloveMigration
847
843
  #
@@ -892,7 +888,7 @@ module ActiveRecord
892
888
  # when the three columns 'first_name', 'last_name' and 'full_name' exist,
893
889
  # even when migrating down:
894
890
  #
895
- # class SplitNameMigration < ActiveRecord::Migration[7.2]
891
+ # class SplitNameMigration < ActiveRecord::Migration[8.0]
896
892
  # def change
897
893
  # add_column :users, :first_name, :string
898
894
  # add_column :users, :last_name, :string
@@ -920,7 +916,7 @@ module ActiveRecord
920
916
  # In the following example, the new column +published+ will be given
921
917
  # the value +true+ for all existing records.
922
918
  #
923
- # class AddPublishedToPosts < ActiveRecord::Migration[7.2]
919
+ # class AddPublishedToPosts < ActiveRecord::Migration[8.0]
924
920
  # def change
925
921
  # add_column :posts, :published, :boolean, default: false
926
922
  # up_only do
@@ -972,16 +968,16 @@ module ActiveRecord
972
968
  when :down then announce "reverting"
973
969
  end
974
970
 
975
- time = nil
971
+ time_elapsed = nil
976
972
  ActiveRecord::Tasks::DatabaseTasks.migration_connection.pool.with_connection do |conn|
977
- time = Benchmark.measure do
973
+ time_elapsed = ActiveSupport::Benchmark.realtime do
978
974
  exec_migration(conn, direction)
979
975
  end
980
976
  end
981
977
 
982
978
  case direction
983
- when :up then announce "migrated (%.4fs)" % time.real; write
984
- when :down then announce "reverted (%.4fs)" % time.real; write
979
+ when :up then announce "migrated (%.4fs)" % time_elapsed; write
980
+ when :down then announce "reverted (%.4fs)" % time_elapsed; write
985
981
  end
986
982
  end
987
983
 
@@ -1022,8 +1018,8 @@ module ActiveRecord
1022
1018
  def say_with_time(message)
1023
1019
  say(message)
1024
1020
  result = nil
1025
- time = Benchmark.measure { result = yield }
1026
- say "%.4fs" % time.real, :subitem
1021
+ time_elapsed = ActiveSupport::Benchmark.realtime { result = yield }
1022
+ say "%.4fs" % time_elapsed, :subitem
1027
1023
  say("#{result} rows", :subitem) if result.is_a?(Integer)
1028
1024
  result
1029
1025
  end
@@ -276,15 +276,14 @@ module ActiveRecord
276
276
  end
277
277
 
278
278
  @table_name = value
279
- @quoted_table_name = nil
280
279
  @arel_table = nil
281
280
  @sequence_name = nil unless @explicit_sequence_name
282
281
  @predicate_builder = nil
283
282
  end
284
283
 
285
- # Returns a quoted version of the table name, used to construct SQL statements.
284
+ # Returns a quoted version of the table name.
286
285
  def quoted_table_name
287
- @quoted_table_name ||= adapter_class.quote_table_name(table_name)
286
+ adapter_class.quote_table_name(table_name)
288
287
  end
289
288
 
290
289
  # Computes the table name, (re)sets it internally, and returns it.
@@ -502,7 +501,7 @@ module ActiveRecord
502
501
  # when just after creating a table you want to populate it with some default
503
502
  # values, e.g.:
504
503
  #
505
- # class CreateJobLevels < ActiveRecord::Migration[7.2]
504
+ # class CreateJobLevels < ActiveRecord::Migration[8.0]
506
505
  # def up
507
506
  # create_table :job_levels do |t|
508
507
  # t.integer :id
@@ -524,12 +524,12 @@ module ActiveRecord
524
524
  unless reject_new_record?(association_name, attributes)
525
525
  association.reader.build(attributes.except(*UNASSIGNABLE_KEYS))
526
526
  end
527
- elsif existing_record = find_record_by_id(existing_records, attributes["id"])
527
+ elsif existing_record = find_record_by_id(association.klass, existing_records, attributes["id"])
528
528
  unless call_reject_if(association_name, attributes)
529
529
  # Make sure we are operating on the actual object which is in the association's
530
530
  # proxy_target array (either by finding it, or adding it if not found)
531
531
  # Take into account that the proxy_target may have changed due to callbacks
532
- target_record = find_record_by_id(association.target, attributes["id"])
532
+ target_record = find_record_by_id(association.klass, association.target, attributes["id"])
533
533
  if target_record
534
534
  existing_record = target_record
535
535
  else
@@ -621,10 +621,8 @@ module ActiveRecord
621
621
  model, "id", record_id)
622
622
  end
623
623
 
624
- def find_record_by_id(records, id)
625
- return if records.empty?
626
-
627
- if records.first.class.composite_primary_key?
624
+ def find_record_by_id(klass, records, id)
625
+ if klass.composite_primary_key?
628
626
  id = Array(id).map(&:to_s)
629
627
  records.find { |record| Array(record.id).map(&:to_s) == id }
630
628
  else