activerecord 7.2.1.1 → 8.0.0.rc1

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 (123) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +220 -756
  3. data/README.rdoc +1 -1
  4. data/lib/active_record/associations/association.rb +25 -5
  5. data/lib/active_record/associations/builder/association.rb +7 -6
  6. data/lib/active_record/associations/collection_association.rb +10 -8
  7. data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
  8. data/lib/active_record/associations/has_many_through_association.rb +10 -3
  9. data/lib/active_record/associations/join_dependency/join_association.rb +3 -2
  10. data/lib/active_record/associations/join_dependency.rb +4 -4
  11. data/lib/active_record/associations/preloader/association.rb +2 -2
  12. data/lib/active_record/associations/singular_association.rb +8 -3
  13. data/lib/active_record/associations.rb +34 -4
  14. data/lib/active_record/asynchronous_queries_tracker.rb +28 -24
  15. data/lib/active_record/attribute_assignment.rb +9 -1
  16. data/lib/active_record/attribute_methods/primary_key.rb +2 -7
  17. data/lib/active_record/attribute_methods/time_zone_conversion.rb +6 -12
  18. data/lib/active_record/attributes.rb +1 -2
  19. data/lib/active_record/autosave_association.rb +69 -27
  20. data/lib/active_record/callbacks.rb +1 -1
  21. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +16 -10
  22. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +0 -1
  23. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +0 -1
  24. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +26 -9
  25. data/lib/active_record/connection_adapters/abstract/database_statements.rb +90 -43
  26. data/lib/active_record/connection_adapters/abstract/query_cache.rb +12 -4
  27. data/lib/active_record/connection_adapters/abstract/quoting.rb +1 -1
  28. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +4 -5
  29. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +7 -2
  30. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +34 -7
  31. data/lib/active_record/connection_adapters/abstract/transaction.rb +15 -5
  32. data/lib/active_record/connection_adapters/abstract_adapter.rb +24 -26
  33. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +28 -42
  34. data/lib/active_record/connection_adapters/mysql/quoting.rb +0 -8
  35. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +2 -8
  36. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +43 -45
  37. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +42 -98
  38. data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -8
  39. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -42
  40. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
  41. data/lib/active_record/connection_adapters/postgresql/oid/cidr.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 +0 -11
  45. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +1 -11
  46. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +1 -1
  47. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +54 -14
  48. data/lib/active_record/connection_adapters/postgresql_adapter.rb +45 -97
  49. data/lib/active_record/connection_adapters/schema_cache.rb +1 -3
  50. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +76 -100
  51. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +0 -6
  52. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +13 -0
  53. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +8 -1
  54. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +53 -12
  55. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +37 -67
  56. data/lib/active_record/connection_adapters/trilogy_adapter.rb +0 -17
  57. data/lib/active_record/connection_adapters.rb +0 -56
  58. data/lib/active_record/connection_handling.rb +22 -0
  59. data/lib/active_record/core.rb +28 -18
  60. data/lib/active_record/database_configurations/connection_url_resolver.rb +1 -1
  61. data/lib/active_record/encryption/config.rb +3 -1
  62. data/lib/active_record/encryption/encryptable_record.rb +4 -4
  63. data/lib/active_record/encryption/encrypted_attribute_type.rb +10 -1
  64. data/lib/active_record/encryption/encryptor.rb +15 -8
  65. data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -2
  66. data/lib/active_record/encryption/key_provider.rb +1 -1
  67. data/lib/active_record/encryption/scheme.rb +8 -1
  68. data/lib/active_record/encryption.rb +2 -0
  69. data/lib/active_record/enum.rb +54 -75
  70. data/lib/active_record/errors.rb +13 -5
  71. data/lib/active_record/fixtures.rb +0 -2
  72. data/lib/active_record/future_result.rb +14 -10
  73. data/lib/active_record/gem_version.rb +4 -4
  74. data/lib/active_record/insert_all.rb +1 -1
  75. data/lib/active_record/locking/optimistic.rb +1 -1
  76. data/lib/active_record/log_subscriber.rb +5 -11
  77. data/lib/active_record/marshalling.rb +4 -1
  78. data/lib/active_record/migration/command_recorder.rb +22 -5
  79. data/lib/active_record/migration/compatibility.rb +5 -2
  80. data/lib/active_record/migration.rb +35 -38
  81. data/lib/active_record/model_schema.rb +4 -6
  82. data/lib/active_record/nested_attributes.rb +11 -2
  83. data/lib/active_record/persistence.rb +128 -130
  84. data/lib/active_record/query_cache.rb +0 -4
  85. data/lib/active_record/query_logs.rb +102 -50
  86. data/lib/active_record/query_logs_formatter.rb +17 -28
  87. data/lib/active_record/querying.rb +8 -8
  88. data/lib/active_record/railtie.rb +9 -38
  89. data/lib/active_record/railties/databases.rake +1 -1
  90. data/lib/active_record/reflection.rb +23 -23
  91. data/lib/active_record/relation/batches/batch_enumerator.rb +4 -3
  92. data/lib/active_record/relation/batches.rb +132 -72
  93. data/lib/active_record/relation/calculations.rb +41 -40
  94. data/lib/active_record/relation/delegation.rb +25 -14
  95. data/lib/active_record/relation/finder_methods.rb +18 -18
  96. data/lib/active_record/relation/merger.rb +8 -8
  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 +14 -1
  100. data/lib/active_record/relation/query_methods.rb +122 -71
  101. data/lib/active_record/relation/spawn_methods.rb +1 -1
  102. data/lib/active_record/relation.rb +79 -61
  103. data/lib/active_record/result.rb +66 -4
  104. data/lib/active_record/sanitization.rb +7 -6
  105. data/lib/active_record/schema_dumper.rb +5 -0
  106. data/lib/active_record/schema_migration.rb +2 -1
  107. data/lib/active_record/scoping/named.rb +5 -2
  108. data/lib/active_record/statement_cache.rb +12 -12
  109. data/lib/active_record/store.rb +7 -3
  110. data/lib/active_record/table_metadata.rb +1 -3
  111. data/lib/active_record/tasks/database_tasks.rb +40 -47
  112. data/lib/active_record/tasks/mysql_database_tasks.rb +0 -2
  113. data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -2
  114. data/lib/active_record/test_fixtures.rb +12 -0
  115. data/lib/active_record/testing/query_assertions.rb +2 -2
  116. data/lib/active_record/token_for.rb +1 -1
  117. data/lib/active_record/validations/uniqueness.rb +9 -8
  118. data/lib/active_record.rb +15 -45
  119. data/lib/arel/collectors/bind.rb +1 -1
  120. data/lib/arel/table.rb +3 -7
  121. data/lib/arel/visitors/sqlite.rb +25 -0
  122. metadata +10 -11
  123. data/lib/active_record/relation/record_fetch_warning.rb +0 -52
@@ -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
@@ -250,7 +247,7 @@ module ActiveRecord
250
247
  #
251
248
  # Example of a simple migration:
252
249
  #
253
- # class AddSsl < ActiveRecord::Migration[7.2]
250
+ # class AddSsl < ActiveRecord::Migration[8.0]
254
251
  # def up
255
252
  # add_column :accounts, :ssl_enabled, :boolean, default: true
256
253
  # end
@@ -270,7 +267,7 @@ module ActiveRecord
270
267
  #
271
268
  # Example of a more complex migration that also needs to initialize data:
272
269
  #
273
- # class AddSystemSettings < ActiveRecord::Migration[7.2]
270
+ # class AddSystemSettings < ActiveRecord::Migration[8.0]
274
271
  # def up
275
272
  # create_table :system_settings do |t|
276
273
  # t.string :name
@@ -357,7 +354,7 @@ module ActiveRecord
357
354
  #
358
355
  # === Deletion
359
356
  #
360
- # * <tt>drop_table(name)</tt>: Drops the table called +name+.
357
+ # * <tt>drop_table(*names)</tt>: Drops the given tables.
361
358
  # * <tt>drop_join_table(table_1, table_2, options)</tt>: Drops the join table
362
359
  # specified by the given arguments.
363
360
  # * <tt>remove_column(table_name, column_name, type, options)</tt>: Removes the column
@@ -399,7 +396,7 @@ module ActiveRecord
399
396
  # $ bin/rails generate migration add_fieldname_to_tablename fieldname:string
400
397
  #
401
398
  # 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]
399
+ # class AddFieldnameToTablename < ActiveRecord::Migration[8.0]
403
400
  # def change
404
401
  # add_column :tablenames, :fieldname, :string
405
402
  # end
@@ -425,7 +422,7 @@ module ActiveRecord
425
422
  #
426
423
  # Not all migrations change the schema. Some just fix the data:
427
424
  #
428
- # class RemoveEmptyTags < ActiveRecord::Migration[7.2]
425
+ # class RemoveEmptyTags < ActiveRecord::Migration[8.0]
429
426
  # def up
430
427
  # Tag.all.each { |tag| tag.destroy if tag.pages.empty? }
431
428
  # end
@@ -438,7 +435,7 @@ module ActiveRecord
438
435
  #
439
436
  # Others remove columns when they migrate up instead of down:
440
437
  #
441
- # class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[7.2]
438
+ # class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[8.0]
442
439
  # def up
443
440
  # remove_column :items, :incomplete_items_count
444
441
  # remove_column :items, :completed_items_count
@@ -452,7 +449,7 @@ module ActiveRecord
452
449
  #
453
450
  # And sometimes you need to do something in SQL not abstracted directly by migrations:
454
451
  #
455
- # class MakeJoinUnique < ActiveRecord::Migration[7.2]
452
+ # class MakeJoinUnique < ActiveRecord::Migration[8.0]
456
453
  # def up
457
454
  # execute "ALTER TABLE `pages_linked_pages` ADD UNIQUE `page_id_linked_page_id` (`page_id`,`linked_page_id`)"
458
455
  # end
@@ -469,7 +466,7 @@ module ActiveRecord
469
466
  # <tt>Base#reset_column_information</tt> in order to ensure that the model has the
470
467
  # latest column data from after the new column was added. Example:
471
468
  #
472
- # class AddPeopleSalary < ActiveRecord::Migration[7.2]
469
+ # class AddPeopleSalary < ActiveRecord::Migration[8.0]
473
470
  # def up
474
471
  # add_column :people, :salary, :integer
475
472
  # Person.reset_column_information
@@ -531,7 +528,7 @@ module ActiveRecord
531
528
  # To define a reversible migration, define the +change+ method in your
532
529
  # migration like this:
533
530
  #
534
- # class TenderloveMigration < ActiveRecord::Migration[7.2]
531
+ # class TenderloveMigration < ActiveRecord::Migration[8.0]
535
532
  # def change
536
533
  # create_table(:horses) do |t|
537
534
  # t.column :content, :text
@@ -561,7 +558,7 @@ module ActiveRecord
561
558
  # can't execute inside a transaction though, and for these situations
562
559
  # you can turn the automatic transactions off.
563
560
  #
564
- # class ChangeEnum < ActiveRecord::Migration[7.2]
561
+ # class ChangeEnum < ActiveRecord::Migration[8.0]
565
562
  # disable_ddl_transaction!
566
563
  #
567
564
  # def up
@@ -604,7 +601,7 @@ module ActiveRecord
604
601
  end
605
602
  end
606
603
 
607
- def drop_table(table_name, **options)
604
+ def drop_table(*table_names, **options)
608
605
  if block_given?
609
606
  super { |t| yield compatible_table_definition(t) }
610
607
  else
@@ -681,10 +678,6 @@ module ActiveRecord
681
678
  paths = all_configs.flat_map { |config| config.migrations_paths || Migrator.migrations_paths }.uniq
682
679
  @file_watcher.new([], paths.index_with(["rb"]), &block)
683
680
  end
684
-
685
- def connection
686
- ActiveRecord::Tasks::DatabaseTasks.migration_connection
687
- end
688
681
  end
689
682
 
690
683
  class << self
@@ -715,13 +708,7 @@ module ActiveRecord
715
708
 
716
709
  def load_schema_if_pending!
717
710
  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
711
+ load_schema!
725
712
  end
726
713
 
727
714
  check_pending_migrations
@@ -785,6 +772,16 @@ module ActiveRecord
785
772
  def env
786
773
  ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
787
774
  end
775
+
776
+ def load_schema!
777
+ # Roundtrip to Rake to allow plugins to hook into database initialization.
778
+ root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
779
+
780
+ FileUtils.cd(root) do
781
+ Base.connection_handler.clear_all_connections!(:all)
782
+ system("bin/rails db:test:prepare")
783
+ end
784
+ end
788
785
  end
789
786
 
790
787
  def disable_ddl_transaction # :nodoc:
@@ -822,7 +819,7 @@ module ActiveRecord
822
819
  # and create the table 'apples' on the way up, and the reverse
823
820
  # on the way down.
824
821
  #
825
- # class FixTLMigration < ActiveRecord::Migration[7.2]
822
+ # class FixTLMigration < ActiveRecord::Migration[8.0]
826
823
  # def change
827
824
  # revert do
828
825
  # create_table(:horses) do |t|
@@ -841,7 +838,7 @@ module ActiveRecord
841
838
  #
842
839
  # require_relative "20121212123456_tenderlove_migration"
843
840
  #
844
- # class FixupTLMigration < ActiveRecord::Migration[7.2]
841
+ # class FixupTLMigration < ActiveRecord::Migration[8.0]
845
842
  # def change
846
843
  # revert TenderloveMigration
847
844
  #
@@ -892,7 +889,7 @@ module ActiveRecord
892
889
  # when the three columns 'first_name', 'last_name' and 'full_name' exist,
893
890
  # even when migrating down:
894
891
  #
895
- # class SplitNameMigration < ActiveRecord::Migration[7.2]
892
+ # class SplitNameMigration < ActiveRecord::Migration[8.0]
896
893
  # def change
897
894
  # add_column :users, :first_name, :string
898
895
  # add_column :users, :last_name, :string
@@ -920,7 +917,7 @@ module ActiveRecord
920
917
  # In the following example, the new column +published+ will be given
921
918
  # the value +true+ for all existing records.
922
919
  #
923
- # class AddPublishedToPosts < ActiveRecord::Migration[7.2]
920
+ # class AddPublishedToPosts < ActiveRecord::Migration[8.0]
924
921
  # def change
925
922
  # add_column :posts, :published, :boolean, default: false
926
923
  # up_only do
@@ -972,16 +969,16 @@ module ActiveRecord
972
969
  when :down then announce "reverting"
973
970
  end
974
971
 
975
- time = nil
972
+ time_elapsed = nil
976
973
  ActiveRecord::Tasks::DatabaseTasks.migration_connection.pool.with_connection do |conn|
977
- time = Benchmark.measure do
974
+ time_elapsed = ActiveSupport::Benchmark.realtime do
978
975
  exec_migration(conn, direction)
979
976
  end
980
977
  end
981
978
 
982
979
  case direction
983
- when :up then announce "migrated (%.4fs)" % time.real; write
984
- when :down then announce "reverted (%.4fs)" % time.real; write
980
+ when :up then announce "migrated (%.4fs)" % time_elapsed; write
981
+ when :down then announce "reverted (%.4fs)" % time_elapsed; write
985
982
  end
986
983
  end
987
984
 
@@ -1022,8 +1019,8 @@ module ActiveRecord
1022
1019
  def say_with_time(message)
1023
1020
  say(message)
1024
1021
  result = nil
1025
- time = Benchmark.measure { result = yield }
1026
- say "%.4fs" % time.real, :subitem
1022
+ time_elapsed = ActiveSupport::Benchmark.realtime { result = yield }
1023
+ say "%.4fs" % time_elapsed, :subitem
1027
1024
  say("#{result} rows", :subitem) if result.is_a?(Integer)
1028
1025
  result
1029
1026
  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.
@@ -431,7 +430,6 @@ module ActiveRecord
431
430
  end
432
431
 
433
432
  def columns
434
- load_schema unless @columns
435
433
  @columns ||= columns_hash.values.freeze
436
434
  end
437
435
 
@@ -503,7 +501,7 @@ module ActiveRecord
503
501
  # when just after creating a table you want to populate it with some default
504
502
  # values, e.g.:
505
503
  #
506
- # class CreateJobLevels < ActiveRecord::Migration[7.2]
504
+ # class CreateJobLevels < ActiveRecord::Migration[8.0]
507
505
  # def up
508
506
  # create_table :job_levels do |t|
509
507
  # t.integer :id
@@ -595,7 +593,7 @@ module ActiveRecord
595
593
  columns_hash = columns_hash.except(*ignored_columns) unless ignored_columns.empty?
596
594
  @columns_hash = columns_hash.freeze
597
595
 
598
- super
596
+ _default_attributes # Precompute to cache DB-dependent attribute types
599
597
  end
600
598
 
601
599
  # Guesses the table name, but does not decorate it with prefix and suffix information.
@@ -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 = existing_records.detect { |record| record.id.to_s == attributes["id"].to_s }
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 = association.target.detect { |record| record.id.to_s == attributes["id"].to_s }
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
@@ -620,5 +620,14 @@ module ActiveRecord
620
620
  raise RecordNotFound.new("Couldn't find #{model} with ID=#{record_id} for #{self.class.name} with ID=#{id}",
621
621
  model, "id", record_id)
622
622
  end
623
+
624
+ def find_record_by_id(klass, records, id)
625
+ if klass.composite_primary_key?
626
+ id = Array(id).map(&:to_s)
627
+ records.find { |record| Array(record.id).map(&:to_s) == id }
628
+ else
629
+ records.find { |record| record.id.to_s == id.to_s }
630
+ end
631
+ end
623
632
  end
624
633
  end
@@ -248,18 +248,16 @@ module ActiveRecord
248
248
 
249
249
  im = Arel::InsertManager.new(arel_table)
250
250
 
251
- with_connection do |c|
252
- if values.empty?
253
- im.insert(connection.empty_insert_statement_value(primary_key))
254
- else
255
- im.insert(values.transform_keys { |name| arel_table[name] })
256
- end
257
-
258
- connection.insert(
259
- im, "#{self} Create", primary_key || false, primary_key_value,
260
- returning: returning
261
- )
251
+ if values.empty?
252
+ im.insert(connection.empty_insert_statement_value(primary_key))
253
+ else
254
+ im.insert(values.transform_keys { |name| arel_table[name] })
262
255
  end
256
+
257
+ connection.insert(
258
+ im, "#{self} Create", primary_key || false, primary_key_value,
259
+ returning: returning
260
+ )
263
261
  end
264
262
 
265
263
  def _update_record(values, constraints) # :nodoc:
@@ -812,159 +810,159 @@ module ActiveRecord
812
810
  end
813
811
  end
814
812
 
815
- private
816
- def init_internals
817
- super
818
- @_trigger_destroy_callback = @_trigger_update_callback = nil
819
- @previously_new_record = false
820
- end
813
+ private
814
+ def init_internals
815
+ super
816
+ @_trigger_destroy_callback = @_trigger_update_callback = nil
817
+ @previously_new_record = false
818
+ end
821
819
 
822
- def strict_loaded_associations
823
- @association_cache.find_all do |_, assoc|
824
- assoc.owner.strict_loading? && !assoc.owner.strict_loading_n_plus_one_only?
825
- end.map(&:first)
826
- end
820
+ def strict_loaded_associations
821
+ @association_cache.find_all do |_, assoc|
822
+ assoc.owner.strict_loading? && !assoc.owner.strict_loading_n_plus_one_only?
823
+ end.map(&:first)
824
+ end
827
825
 
828
- def _find_record(options)
829
- all_queries = options ? options[:all_queries] : nil
830
- base = self.class.all(all_queries: all_queries).preload(strict_loaded_associations)
826
+ def _find_record(options)
827
+ all_queries = options ? options[:all_queries] : nil
828
+ base = self.class.all(all_queries: all_queries).preload(strict_loaded_associations)
831
829
 
832
- if options && options[:lock]
833
- base.lock(options[:lock]).find_by!(_in_memory_query_constraints_hash)
834
- else
835
- base.find_by!(_in_memory_query_constraints_hash)
830
+ if options && options[:lock]
831
+ base.lock(options[:lock]).find_by!(_in_memory_query_constraints_hash)
832
+ else
833
+ base.find_by!(_in_memory_query_constraints_hash)
834
+ end
836
835
  end
837
- end
838
836
 
839
- def _in_memory_query_constraints_hash
840
- if self.class.query_constraints_list.nil?
841
- { @primary_key => id }
842
- else
843
- self.class.query_constraints_list.index_with do |column_name|
844
- attribute(column_name)
837
+ def _in_memory_query_constraints_hash
838
+ if self.class.query_constraints_list.nil?
839
+ { @primary_key => id }
840
+ else
841
+ self.class.query_constraints_list.index_with do |column_name|
842
+ attribute(column_name)
843
+ end
845
844
  end
846
845
  end
847
- end
848
846
 
849
- def apply_scoping?(options)
850
- !(options && options[:unscoped]) &&
851
- (self.class.default_scopes?(all_queries: true) || self.class.global_current_scope)
852
- end
847
+ def apply_scoping?(options)
848
+ !(options && options[:unscoped]) &&
849
+ (self.class.default_scopes?(all_queries: true) || self.class.global_current_scope)
850
+ end
853
851
 
854
- def _query_constraints_hash
855
- if self.class.query_constraints_list.nil?
856
- { @primary_key => id_in_database }
857
- else
858
- self.class.query_constraints_list.index_with do |column_name|
859
- attribute_in_database(column_name)
852
+ def _query_constraints_hash
853
+ if self.class.query_constraints_list.nil?
854
+ { @primary_key => id_in_database }
855
+ else
856
+ self.class.query_constraints_list.index_with do |column_name|
857
+ attribute_in_database(column_name)
858
+ end
860
859
  end
861
860
  end
862
- end
863
861
 
864
- # A hook to be overridden by association modules.
865
- def destroy_associations
866
- end
867
-
868
- def destroy_row
869
- _delete_row
870
- end
871
-
872
- def _delete_row
873
- self.class._delete_record(_query_constraints_hash)
874
- end
862
+ # A hook to be overridden by association modules.
863
+ def destroy_associations
864
+ end
875
865
 
876
- def _touch_row(attribute_names, time)
877
- time ||= current_time_from_proper_timezone
866
+ def destroy_row
867
+ _delete_row
868
+ end
878
869
 
879
- attribute_names.each do |attr_name|
880
- _write_attribute(attr_name, time)
870
+ def _delete_row
871
+ self.class._delete_record(_query_constraints_hash)
881
872
  end
882
873
 
883
- _update_row(attribute_names, "touch")
884
- end
874
+ def _touch_row(attribute_names, time)
875
+ time ||= current_time_from_proper_timezone
885
876
 
886
- def _update_row(attribute_names, attempted_action = "update")
887
- self.class._update_record(
888
- attributes_with_values(attribute_names),
889
- _query_constraints_hash
890
- )
891
- end
877
+ attribute_names.each do |attr_name|
878
+ _write_attribute(attr_name, time)
879
+ end
892
880
 
893
- def create_or_update(**, &block)
894
- _raise_readonly_record_error if readonly?
895
- return false if destroyed?
896
- result = new_record? ? _create_record(&block) : _update_record(&block)
897
- result != false
898
- end
881
+ _update_row(attribute_names, "touch")
882
+ end
899
883
 
900
- # Updates the associated record with values matching those of the instance attributes.
901
- # Returns the number of affected rows.
902
- def _update_record(attribute_names = self.attribute_names)
903
- attribute_names = attributes_for_update(attribute_names)
884
+ def _update_row(attribute_names, attempted_action = "update")
885
+ self.class._update_record(
886
+ attributes_with_values(attribute_names),
887
+ _query_constraints_hash
888
+ )
889
+ end
904
890
 
905
- if attribute_names.empty?
906
- affected_rows = 0
907
- @_trigger_update_callback = true
908
- else
909
- affected_rows = _update_row(attribute_names)
910
- @_trigger_update_callback = affected_rows == 1
891
+ def create_or_update(**, &block)
892
+ _raise_readonly_record_error if readonly?
893
+ return false if destroyed?
894
+ result = new_record? ? _create_record(&block) : _update_record(&block)
895
+ result != false
911
896
  end
912
897
 
913
- @previously_new_record = false
898
+ # Updates the associated record with values matching those of the instance attributes.
899
+ # Returns the number of affected rows.
900
+ def _update_record(attribute_names = self.attribute_names)
901
+ attribute_names = attributes_for_update(attribute_names)
914
902
 
915
- yield(self) if block_given?
903
+ if attribute_names.empty?
904
+ affected_rows = 0
905
+ @_trigger_update_callback = true
906
+ else
907
+ affected_rows = _update_row(attribute_names)
908
+ @_trigger_update_callback = affected_rows == 1
909
+ end
916
910
 
917
- affected_rows
918
- end
911
+ @previously_new_record = false
919
912
 
920
- # Creates a record with values matching those of the instance attributes
921
- # and returns its id.
922
- def _create_record(attribute_names = self.attribute_names)
923
- attribute_names = attributes_for_create(attribute_names)
913
+ yield(self) if block_given?
924
914
 
925
- self.class.with_connection do |connection|
926
- returning_columns = self.class._returning_columns_for_insert(connection)
915
+ affected_rows
916
+ end
927
917
 
928
- returning_values = self.class._insert_record(
929
- connection,
930
- attributes_with_values(attribute_names),
931
- returning_columns
932
- )
918
+ # Creates a record with values matching those of the instance attributes
919
+ # and returns its id.
920
+ def _create_record(attribute_names = self.attribute_names)
921
+ attribute_names = attributes_for_create(attribute_names)
933
922
 
934
- returning_columns.zip(returning_values).each do |column, value|
935
- _write_attribute(column, value) if !_read_attribute(column)
936
- end if returning_values
937
- end
923
+ self.class.with_connection do |connection|
924
+ returning_columns = self.class._returning_columns_for_insert(connection)
938
925
 
939
- @new_record = false
940
- @previously_new_record = true
926
+ returning_values = self.class._insert_record(
927
+ connection,
928
+ attributes_with_values(attribute_names),
929
+ returning_columns
930
+ )
941
931
 
942
- yield(self) if block_given?
932
+ returning_columns.zip(returning_values).each do |column, value|
933
+ _write_attribute(column, value) if !_read_attribute(column)
934
+ end if returning_values
935
+ end
943
936
 
944
- id
945
- end
937
+ @new_record = false
938
+ @previously_new_record = true
946
939
 
947
- def verify_readonly_attribute(name)
948
- raise ActiveRecordError, "#{name} is marked as readonly" if self.class.readonly_attribute?(name)
949
- end
940
+ yield(self) if block_given?
950
941
 
951
- def _raise_record_not_destroyed
952
- @_association_destroy_exception ||= nil
953
- key = self.class.primary_key
954
- raise @_association_destroy_exception || RecordNotDestroyed.new("Failed to destroy #{self.class} with #{key}=#{id}", self)
955
- ensure
956
- @_association_destroy_exception = nil
957
- end
942
+ id
943
+ end
958
944
 
959
- def _raise_readonly_record_error
960
- raise ReadOnlyRecord, "#{self.class} is marked as readonly"
961
- end
945
+ def verify_readonly_attribute(name)
946
+ raise ActiveRecordError, "#{name} is marked as readonly" if self.class.readonly_attribute?(name)
947
+ end
962
948
 
963
- def _raise_record_not_touched_error
964
- raise ActiveRecordError, <<~MSG.squish
965
- Cannot touch on a new or destroyed record object. Consider using
966
- persisted?, new_record?, or destroyed? before touching.
967
- MSG
968
- end
949
+ def _raise_record_not_destroyed
950
+ @_association_destroy_exception ||= nil
951
+ key = self.class.primary_key
952
+ raise @_association_destroy_exception || RecordNotDestroyed.new("Failed to destroy #{self.class} with #{key}=#{id}", self)
953
+ ensure
954
+ @_association_destroy_exception = nil
955
+ end
956
+
957
+ def _raise_readonly_record_error
958
+ raise ReadOnlyRecord, "#{self.class} is marked as readonly"
959
+ end
960
+
961
+ def _raise_record_not_touched_error
962
+ raise ActiveRecordError, <<~MSG.squish
963
+ Cannot touch on a new or destroyed record object. Consider using
964
+ persisted?, new_record?, or destroyed? before touching.
965
+ MSG
966
+ end
969
967
  end
970
968
  end
@@ -43,10 +43,6 @@ module ActiveRecord
43
43
  pool.disable_query_cache!
44
44
  pool.clear_query_cache
45
45
  end
46
-
47
- ActiveRecord::Base.connection_handler.each_connection_pool do |pool|
48
- pool.release_connection if pool.active_connection? && !pool.lease_connection.transaction_open?
49
- end
50
46
  end
51
47
 
52
48
  def self.install_executor_hooks(executor = ActiveSupport::Executor)