activerecord 7.2.3 → 8.1.3

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 (198) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +612 -1055
  3. data/README.rdoc +1 -1
  4. data/lib/active_record/association_relation.rb +2 -1
  5. data/lib/active_record/associations/association.rb +35 -11
  6. data/lib/active_record/associations/builder/association.rb +23 -11
  7. data/lib/active_record/associations/builder/belongs_to.rb +17 -4
  8. data/lib/active_record/associations/builder/collection_association.rb +7 -3
  9. data/lib/active_record/associations/builder/has_one.rb +1 -1
  10. data/lib/active_record/associations/builder/singular_association.rb +33 -5
  11. data/lib/active_record/associations/collection_association.rb +1 -1
  12. data/lib/active_record/associations/collection_proxy.rb +22 -4
  13. data/lib/active_record/associations/deprecation.rb +88 -0
  14. data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
  15. data/lib/active_record/associations/errors.rb +3 -0
  16. data/lib/active_record/associations/has_many_through_association.rb +3 -2
  17. data/lib/active_record/associations/join_dependency.rb +4 -2
  18. data/lib/active_record/associations/preloader/association.rb +2 -2
  19. data/lib/active_record/associations/preloader/batch.rb +7 -1
  20. data/lib/active_record/associations/preloader/branch.rb +1 -0
  21. data/lib/active_record/associations/singular_association.rb +8 -3
  22. data/lib/active_record/associations.rb +192 -24
  23. data/lib/active_record/asynchronous_queries_tracker.rb +28 -24
  24. data/lib/active_record/attribute_methods/primary_key.rb +4 -8
  25. data/lib/active_record/attribute_methods/query.rb +34 -0
  26. data/lib/active_record/attribute_methods/serialization.rb +16 -3
  27. data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -14
  28. data/lib/active_record/attributes.rb +3 -0
  29. data/lib/active_record/autosave_association.rb +69 -27
  30. data/lib/active_record/base.rb +1 -2
  31. data/lib/active_record/coders/json.rb +14 -5
  32. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +35 -28
  33. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +16 -4
  34. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +51 -13
  35. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +412 -88
  36. data/lib/active_record/connection_adapters/abstract/database_statements.rb +137 -75
  37. data/lib/active_record/connection_adapters/abstract/query_cache.rb +27 -5
  38. data/lib/active_record/connection_adapters/abstract/quoting.rb +16 -25
  39. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +11 -7
  40. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +32 -35
  41. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -1
  42. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +122 -32
  43. data/lib/active_record/connection_adapters/abstract/transaction.rb +40 -8
  44. data/lib/active_record/connection_adapters/abstract_adapter.rb +150 -91
  45. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +63 -52
  46. data/lib/active_record/connection_adapters/column.rb +17 -4
  47. data/lib/active_record/connection_adapters/mysql/database_statements.rb +4 -4
  48. data/lib/active_record/connection_adapters/mysql/quoting.rb +0 -8
  49. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +2 -0
  50. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +41 -10
  51. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +73 -46
  52. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +89 -94
  53. data/lib/active_record/connection_adapters/mysql2_adapter.rb +2 -10
  54. data/lib/active_record/connection_adapters/pool_config.rb +7 -7
  55. data/lib/active_record/connection_adapters/postgresql/column.rb +8 -2
  56. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +76 -45
  57. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +3 -3
  58. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +10 -0
  59. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +1 -1
  60. data/lib/active_record/connection_adapters/postgresql/quoting.rb +21 -10
  61. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -4
  62. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +9 -17
  63. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +14 -33
  64. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +71 -32
  65. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +139 -63
  66. data/lib/active_record/connection_adapters/postgresql_adapter.rb +78 -105
  67. data/lib/active_record/connection_adapters/schema_cache.rb +3 -5
  68. data/lib/active_record/connection_adapters/sqlite3/column.rb +8 -2
  69. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +90 -98
  70. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +0 -8
  71. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +0 -6
  72. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +27 -2
  73. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +13 -14
  74. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +102 -37
  75. data/lib/active_record/connection_adapters/statement_pool.rb +4 -2
  76. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +38 -67
  77. data/lib/active_record/connection_adapters/trilogy_adapter.rb +1 -18
  78. data/lib/active_record/connection_adapters.rb +1 -56
  79. data/lib/active_record/connection_handling.rb +25 -2
  80. data/lib/active_record/core.rb +33 -17
  81. data/lib/active_record/counter_cache.rb +33 -8
  82. data/lib/active_record/database_configurations/database_config.rb +9 -1
  83. data/lib/active_record/database_configurations/hash_config.rb +67 -9
  84. data/lib/active_record/database_configurations/url_config.rb +13 -3
  85. data/lib/active_record/database_configurations.rb +7 -3
  86. data/lib/active_record/delegated_type.rb +1 -1
  87. data/lib/active_record/dynamic_matchers.rb +54 -69
  88. data/lib/active_record/encryption/config.rb +3 -1
  89. data/lib/active_record/encryption/encryptable_record.rb +8 -8
  90. data/lib/active_record/encryption/encrypted_attribute_type.rb +11 -2
  91. data/lib/active_record/encryption/encryptor.rb +28 -8
  92. data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -2
  93. data/lib/active_record/encryption/scheme.rb +9 -2
  94. data/lib/active_record/enum.rb +33 -30
  95. data/lib/active_record/errors.rb +33 -9
  96. data/lib/active_record/explain.rb +1 -1
  97. data/lib/active_record/explain_registry.rb +51 -2
  98. data/lib/active_record/filter_attribute_handler.rb +73 -0
  99. data/lib/active_record/fixtures.rb +2 -4
  100. data/lib/active_record/future_result.rb +15 -9
  101. data/lib/active_record/gem_version.rb +2 -2
  102. data/lib/active_record/inheritance.rb +1 -1
  103. data/lib/active_record/insert_all.rb +14 -9
  104. data/lib/active_record/locking/optimistic.rb +8 -1
  105. data/lib/active_record/locking/pessimistic.rb +5 -0
  106. data/lib/active_record/log_subscriber.rb +3 -13
  107. data/lib/active_record/middleware/shard_selector.rb +34 -17
  108. data/lib/active_record/migration/command_recorder.rb +45 -12
  109. data/lib/active_record/migration/compatibility.rb +37 -24
  110. data/lib/active_record/migration/default_schema_versions_formatter.rb +30 -0
  111. data/lib/active_record/migration.rb +48 -42
  112. data/lib/active_record/model_schema.rb +38 -13
  113. data/lib/active_record/nested_attributes.rb +6 -6
  114. data/lib/active_record/persistence.rb +162 -133
  115. data/lib/active_record/query_cache.rb +22 -15
  116. data/lib/active_record/query_logs.rb +100 -52
  117. data/lib/active_record/query_logs_formatter.rb +17 -28
  118. data/lib/active_record/querying.rb +8 -8
  119. data/lib/active_record/railtie.rb +35 -30
  120. data/lib/active_record/railties/controller_runtime.rb +11 -6
  121. data/lib/active_record/railties/databases.rake +26 -38
  122. data/lib/active_record/railties/job_checkpoints.rb +15 -0
  123. data/lib/active_record/railties/job_runtime.rb +10 -11
  124. data/lib/active_record/reflection.rb +53 -21
  125. data/lib/active_record/relation/batches/batch_enumerator.rb +4 -3
  126. data/lib/active_record/relation/batches.rb +147 -73
  127. data/lib/active_record/relation/calculations.rb +52 -40
  128. data/lib/active_record/relation/delegation.rb +25 -15
  129. data/lib/active_record/relation/finder_methods.rb +40 -24
  130. data/lib/active_record/relation/merger.rb +8 -8
  131. data/lib/active_record/relation/predicate_builder/array_handler.rb +3 -1
  132. data/lib/active_record/relation/predicate_builder/association_query_value.rb +9 -9
  133. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +8 -8
  134. data/lib/active_record/relation/predicate_builder/relation_handler.rb +4 -3
  135. data/lib/active_record/relation/predicate_builder.rb +22 -7
  136. data/lib/active_record/relation/query_attribute.rb +3 -1
  137. data/lib/active_record/relation/query_methods.rb +140 -86
  138. data/lib/active_record/relation/spawn_methods.rb +7 -7
  139. data/lib/active_record/relation/where_clause.rb +2 -9
  140. data/lib/active_record/relation.rb +107 -75
  141. data/lib/active_record/result.rb +109 -24
  142. data/lib/active_record/runtime_registry.rb +42 -58
  143. data/lib/active_record/sanitization.rb +9 -6
  144. data/lib/active_record/schema_dumper.rb +18 -11
  145. data/lib/active_record/schema_migration.rb +2 -1
  146. data/lib/active_record/scoping/named.rb +5 -2
  147. data/lib/active_record/scoping.rb +0 -1
  148. data/lib/active_record/signed_id.rb +43 -15
  149. data/lib/active_record/statement_cache.rb +24 -20
  150. data/lib/active_record/store.rb +51 -22
  151. data/lib/active_record/structured_event_subscriber.rb +85 -0
  152. data/lib/active_record/table_metadata.rb +6 -23
  153. data/lib/active_record/tasks/abstract_tasks.rb +76 -0
  154. data/lib/active_record/tasks/database_tasks.rb +85 -85
  155. data/lib/active_record/tasks/mysql_database_tasks.rb +3 -42
  156. data/lib/active_record/tasks/postgresql_database_tasks.rb +7 -40
  157. data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -28
  158. data/lib/active_record/test_databases.rb +14 -4
  159. data/lib/active_record/test_fixtures.rb +39 -2
  160. data/lib/active_record/testing/query_assertions.rb +8 -2
  161. data/lib/active_record/timestamp.rb +4 -2
  162. data/lib/active_record/token_for.rb +1 -1
  163. data/lib/active_record/transaction.rb +2 -5
  164. data/lib/active_record/transactions.rb +37 -16
  165. data/lib/active_record/type/hash_lookup_type_map.rb +2 -1
  166. data/lib/active_record/type/internal/timezone.rb +7 -0
  167. data/lib/active_record/type/json.rb +13 -2
  168. data/lib/active_record/type/serialized.rb +16 -4
  169. data/lib/active_record/type/type_map.rb +1 -1
  170. data/lib/active_record/type_caster/connection.rb +2 -1
  171. data/lib/active_record/validations/associated.rb +1 -1
  172. data/lib/active_record/validations/uniqueness.rb +8 -8
  173. data/lib/active_record.rb +84 -49
  174. data/lib/arel/alias_predication.rb +2 -0
  175. data/lib/arel/collectors/bind.rb +2 -2
  176. data/lib/arel/collectors/sql_string.rb +1 -1
  177. data/lib/arel/collectors/substitute_binds.rb +2 -2
  178. data/lib/arel/crud.rb +6 -11
  179. data/lib/arel/nodes/binary.rb +1 -1
  180. data/lib/arel/nodes/count.rb +2 -2
  181. data/lib/arel/nodes/function.rb +4 -10
  182. data/lib/arel/nodes/named_function.rb +2 -2
  183. data/lib/arel/nodes/node.rb +2 -2
  184. data/lib/arel/nodes/sql_literal.rb +1 -1
  185. data/lib/arel/nodes.rb +0 -2
  186. data/lib/arel/predications.rb +1 -3
  187. data/lib/arel/select_manager.rb +7 -2
  188. data/lib/arel/table.rb +3 -7
  189. data/lib/arel/visitors/dot.rb +0 -3
  190. data/lib/arel/visitors/postgresql.rb +55 -0
  191. data/lib/arel/visitors/sqlite.rb +55 -8
  192. data/lib/arel/visitors/to_sql.rb +3 -21
  193. data/lib/arel.rb +3 -1
  194. data/lib/rails/generators/active_record/application_record/USAGE +1 -1
  195. metadata +16 -13
  196. data/lib/active_record/explain_subscriber.rb +0 -34
  197. data/lib/active_record/normalization.rb +0 -163
  198. data/lib/active_record/relation/record_fetch_warning.rb +0 -52
@@ -60,7 +60,7 @@ module ActiveRecord
60
60
  :reverse_order, :distinct, :create_with, :skip_query_cache]
61
61
 
62
62
  CLAUSE_METHODS = [:where, :having, :from]
63
- INVALID_METHODS_FOR_DELETE_ALL = [:distinct, :with, :with_recursive]
63
+ INVALID_METHODS_FOR_UPDATE_AND_DELETE_ALL = [:distinct, :with, :with_recursive]
64
64
 
65
65
  VALUE_METHODS = MULTI_VALUE_METHODS + SINGLE_VALUE_METHODS + CLAUSE_METHODS
66
66
 
@@ -68,19 +68,26 @@ module ActiveRecord
68
68
  include FinderMethods, Calculations, SpawnMethods, QueryMethods, Batches, Explain, Delegation
69
69
  include SignedId::RelationMethods, TokenFor::RelationMethods
70
70
 
71
- attr_reader :table, :klass, :loaded, :predicate_builder
71
+ attr_reader :table, :model, :loaded, :predicate_builder
72
72
  attr_accessor :skip_preloading_value
73
- alias :model :klass
73
+ alias :klass :model
74
74
  alias :loaded? :loaded
75
75
  alias :locked? :lock_value
76
76
 
77
- def initialize(klass, table: klass.arel_table, predicate_builder: klass.predicate_builder, values: {})
78
- @klass = klass
77
+ def initialize(model, table: nil, predicate_builder: nil, values: {})
78
+ if table
79
+ predicate_builder ||= model.predicate_builder.with(TableMetadata.new(model, table))
80
+ else
81
+ table = model.arel_table
82
+ predicate_builder ||= model.predicate_builder
83
+ end
84
+
85
+ @model = model
79
86
  @table = table
80
87
  @values = values
81
88
  @loaded = false
82
89
  @predicate_builder = predicate_builder
83
- @delegate_to_klass = false
90
+ @delegate_to_model = false
84
91
  @future_result = nil
85
92
  @records = nil
86
93
  @async = false
@@ -93,7 +100,7 @@ module ActiveRecord
93
100
  end
94
101
 
95
102
  def bind_attribute(name, value) # :nodoc:
96
- if reflection = klass._reflect_on_association(name)
103
+ if reflection = model._reflect_on_association(name)
97
104
  name = reflection.foreign_key
98
105
  value = value.read_attribute(reflection.association_primary_key) unless value.nil?
99
106
  end
@@ -440,14 +447,14 @@ module ActiveRecord
440
447
  # Product.where("name like ?", "%Game%").cache_key(:last_reviewed_at)
441
448
  def cache_key(timestamp_column = "updated_at")
442
449
  @cache_keys ||= {}
443
- @cache_keys[timestamp_column] ||= klass.collection_cache_key(self, timestamp_column)
450
+ @cache_keys[timestamp_column] ||= model.collection_cache_key(self, timestamp_column)
444
451
  end
445
452
 
446
453
  def compute_cache_key(timestamp_column = :updated_at) # :nodoc:
447
454
  query_signature = ActiveSupport::Digest.hexdigest(to_sql)
448
- key = "#{klass.model_name.cache_key}/query-#{query_signature}"
455
+ key = "#{model.model_name.cache_key}/query-#{query_signature}"
449
456
 
450
- if collection_cache_versioning
457
+ if model.collection_cache_versioning
451
458
  key
452
459
  else
453
460
  "#{key}-#{compute_cache_version(timestamp_column)}"
@@ -466,7 +473,7 @@ module ActiveRecord
466
473
  #
467
474
  # SELECT COUNT(*), MAX("products"."updated_at") FROM "products" WHERE (name like '%Cosmic Encounter%')
468
475
  def cache_version(timestamp_column = :updated_at)
469
- if collection_cache_versioning
476
+ if model.collection_cache_versioning
470
477
  @cache_versions ||= {}
471
478
  @cache_versions[timestamp_column] ||= compute_cache_version(timestamp_column)
472
479
  end
@@ -485,7 +492,7 @@ module ActiveRecord
485
492
 
486
493
  with_connection do |c|
487
494
  column = c.visitor.compile(table[timestamp_column])
488
- select_values = "COUNT(*) AS #{adapter_class.quote_column_name("size")}, MAX(%s) AS timestamp"
495
+ select_values = "COUNT(*) AS #{model.adapter_class.quote_column_name("size")}, MAX(%s) AS timestamp"
489
496
 
490
497
  if collection.has_limit_or_offset?
491
498
  query = collection.select("#{column} AS collection_cache_key_timestamp")
@@ -502,7 +509,7 @@ module ActiveRecord
502
509
  size, timestamp = c.select_rows(arel, nil).first
503
510
 
504
511
  if size
505
- column_type = klass.type_for_attribute(timestamp_column)
512
+ column_type = model.type_for_attribute(timestamp_column)
506
513
  timestamp = column_type.deserialize(timestamp)
507
514
  else
508
515
  size = 0
@@ -511,7 +518,7 @@ module ActiveRecord
511
518
  end
512
519
 
513
520
  if timestamp
514
- "#{size}-#{timestamp.utc.to_fs(cache_timestamp_format)}"
521
+ "#{size}-#{timestamp.utc.to_fs(model.cache_timestamp_format)}"
515
522
  else
516
523
  "#{size}"
517
524
  end
@@ -542,7 +549,7 @@ module ActiveRecord
542
549
  # Please check unscoped if you want to remove all previous scopes (including
543
550
  # the default_scope) during the execution of a block.
544
551
  def scoping(all_queries: nil, &block)
545
- registry = klass.scope_registry
552
+ registry = model.scope_registry
546
553
  if global_scope?(registry) && all_queries == false
547
554
  raise ArgumentError, "Scoping is set to apply to all queries and cannot be unset in a nested block."
548
555
  elsif already_in_scope?(registry)
@@ -553,11 +560,11 @@ module ActiveRecord
553
560
  end
554
561
 
555
562
  def _exec_scope(...) # :nodoc:
556
- @delegate_to_klass = true
557
- registry = klass.scope_registry
563
+ @delegate_to_model = true
564
+ registry = model.scope_registry
558
565
  _scoping(nil, registry) { instance_exec(...) || self }
559
566
  ensure
560
- @delegate_to_klass = false
567
+ @delegate_to_model = false
561
568
  end
562
569
 
563
570
  # Updates all records in the current relation with details given. This method constructs a single SQL UPDATE
@@ -593,31 +600,41 @@ module ActiveRecord
593
600
 
594
601
  return 0 if @none
595
602
 
603
+ invalid_methods = INVALID_METHODS_FOR_UPDATE_AND_DELETE_ALL.select do |method|
604
+ value = @values[method]
605
+ method == :distinct ? value : value&.any?
606
+ end
607
+ if invalid_methods.any?
608
+ ActiveRecord.deprecator.warn <<~MESSAGE
609
+ `#{invalid_methods.join(', ')}` is not supported by `update_all` and was never included in the generated query.
610
+
611
+ Calling `#{invalid_methods.join(', ')}` with `update_all` will raise an error in Rails 8.2.
612
+ MESSAGE
613
+ end
614
+
596
615
  if updates.is_a?(Hash)
597
- if klass.locking_enabled? &&
598
- !updates.key?(klass.locking_column) &&
599
- !updates.key?(klass.locking_column.to_sym)
600
- attr = table[klass.locking_column]
616
+ if model.locking_enabled? &&
617
+ !updates.key?(model.locking_column) &&
618
+ !updates.key?(model.locking_column.to_sym)
619
+ attr = table[model.locking_column]
601
620
  updates[attr.name] = _increment_attribute(attr)
602
621
  end
603
622
  values = _substitute_values(updates)
604
623
  else
605
- values = Arel.sql(klass.sanitize_sql_for_assignment(updates, table.name))
624
+ values = Arel.sql(model.sanitize_sql_for_assignment(updates, table.name))
606
625
  end
607
626
 
608
- klass.with_connection do |c|
609
- arel = eager_loading? ? apply_join_dependency.arel : build_arel(c)
627
+ model.with_connection do |c|
628
+ arel = eager_loading? ? apply_join_dependency.arel : arel()
610
629
  arel.source.left = table
611
630
 
612
- group_values_arel_columns = arel_columns(group_values.uniq)
613
- having_clause_ast = having_clause.ast unless having_clause.empty?
614
- key = if klass.composite_primary_key?
631
+ key = if model.composite_primary_key?
615
632
  primary_key.map { |pk| table[pk] }
616
633
  else
617
634
  table[primary_key]
618
635
  end
619
- stmt = arel.compile_update(values, key, having_clause_ast, group_values_arel_columns)
620
- c.update(stmt, "#{klass} Update All").tap { reset }
636
+ stmt = arel.compile_update(values, key)
637
+ c.update(stmt, "#{model} Update All").tap { reset }
621
638
  end
622
639
  end
623
640
 
@@ -625,7 +642,7 @@ module ActiveRecord
625
642
  if id == :all
626
643
  each { |record| record.update(attributes) }
627
644
  else
628
- klass.update(id, attributes)
645
+ model.update(id, attributes)
629
646
  end
630
647
  end
631
648
 
@@ -633,7 +650,7 @@ module ActiveRecord
633
650
  if id == :all
634
651
  each { |record| record.update!(attributes) }
635
652
  else
636
- klass.update!(id, attributes)
653
+ model.update!(id, attributes)
637
654
  end
638
655
  end
639
656
 
@@ -852,7 +869,9 @@ module ActiveRecord
852
869
  # Active Record's schema_cache.
853
870
  #
854
871
  # [:on_duplicate]
855
- # Configure the SQL update sentence that will be used in case of conflict.
872
+ # Configure the behavior that will be used in case of conflict. Use `:skip`
873
+ # to ignore any conflicts or provide a safe SQL fragment wrapped with
874
+ # `Arel.sql`.
856
875
  #
857
876
  # NOTE: If you use this option you must provide all the columns you want to update
858
877
  # by yourself.
@@ -939,7 +958,7 @@ module ActiveRecord
939
958
  names = touch if touch != true
940
959
  names = Array.wrap(names)
941
960
  options = names.extract_options!
942
- touch_updates = klass.touch_attributes_with_time(*names, **options)
961
+ touch_updates = model.touch_attributes_with_time(*names, **options)
943
962
  updates.merge!(touch_updates) unless touch_updates.empty?
944
963
  end
945
964
 
@@ -970,7 +989,7 @@ module ActiveRecord
970
989
  # Person.where(name: 'David').touch_all
971
990
  # # => "UPDATE \"people\" SET \"updated_at\" = '2018-01-04 22:55:23.132670' WHERE \"people\".\"name\" = 'David'"
972
991
  def touch_all(*names, time: nil)
973
- update_all klass.touch_attributes_with_time(*names, time: time)
992
+ update_all model.touch_attributes_with_time(*names, time: time)
974
993
  end
975
994
 
976
995
  # Destroys the records by instantiating each
@@ -1003,7 +1022,7 @@ module ActiveRecord
1003
1022
  #
1004
1023
  # Post.where(person_id: 5).where(category: ['Something', 'Else']).delete_all
1005
1024
  #
1006
- # Both calls delete the affected posts all at once with a single DELETE statement.
1025
+ # This call deletes the affected posts all at once with a single DELETE statement.
1007
1026
  # If you need to destroy dependent associations or call your <tt>before_*</tt> or
1008
1027
  # +after_destroy+ callbacks, use the #destroy_all method instead.
1009
1028
  #
@@ -1014,7 +1033,7 @@ module ActiveRecord
1014
1033
  def delete_all
1015
1034
  return 0 if @none
1016
1035
 
1017
- invalid_methods = INVALID_METHODS_FOR_DELETE_ALL.select do |method|
1036
+ invalid_methods = INVALID_METHODS_FOR_UPDATE_AND_DELETE_ALL.select do |method|
1018
1037
  value = @values[method]
1019
1038
  method == :distinct ? value : value&.any?
1020
1039
  end
@@ -1022,20 +1041,18 @@ module ActiveRecord
1022
1041
  raise ActiveRecordError.new("delete_all doesn't support #{invalid_methods.join(', ')}")
1023
1042
  end
1024
1043
 
1025
- klass.with_connection do |c|
1026
- arel = eager_loading? ? apply_join_dependency.arel : build_arel(c)
1044
+ model.with_connection do |c|
1045
+ arel = eager_loading? ? apply_join_dependency.arel : arel()
1027
1046
  arel.source.left = table
1028
1047
 
1029
- group_values_arel_columns = arel_columns(group_values.uniq)
1030
- having_clause_ast = having_clause.ast unless having_clause.empty?
1031
- key = if klass.composite_primary_key?
1048
+ key = if model.composite_primary_key?
1032
1049
  primary_key.map { |pk| table[pk] }
1033
1050
  else
1034
1051
  table[primary_key]
1035
1052
  end
1036
- stmt = arel.compile_delete(key, having_clause_ast, group_values_arel_columns)
1053
+ stmt = arel.compile_delete(key)
1037
1054
 
1038
- c.delete(stmt, "#{klass} Delete All").tap { reset }
1055
+ c.delete(stmt, "#{model} Delete All").tap { reset }
1039
1056
  end
1040
1057
  end
1041
1058
 
@@ -1134,9 +1151,6 @@ module ActiveRecord
1134
1151
  # for queries to actually be executed concurrently. Otherwise it defaults to
1135
1152
  # executing them in the foreground.
1136
1153
  #
1137
- # +load_async+ will also fall back to executing in the foreground in the test environment when transactional
1138
- # fixtures are enabled.
1139
- #
1140
1154
  # If the query was actually executed in the background, the Active Record logs will show
1141
1155
  # it by prefixing the log line with <tt>ASYNC</tt>:
1142
1156
  #
@@ -1146,7 +1160,7 @@ module ActiveRecord
1146
1160
  return load if !c.async_enabled?
1147
1161
 
1148
1162
  unless loaded?
1149
- result = exec_main_query(async: c.current_transaction.closed?)
1163
+ result = exec_main_query(async: !c.current_transaction.joinable?)
1150
1164
 
1151
1165
  if result.is_a?(Array)
1152
1166
  @records = result
@@ -1160,6 +1174,16 @@ module ActiveRecord
1160
1174
  self
1161
1175
  end
1162
1176
 
1177
+ def then(&block) # :nodoc:
1178
+ if @future_result
1179
+ @future_result.then do
1180
+ yield self
1181
+ end
1182
+ else
1183
+ super
1184
+ end
1185
+ end
1186
+
1163
1187
  # Returns <tt>true</tt> if the relation was scheduled on the background
1164
1188
  # thread pool.
1165
1189
  def scheduled?
@@ -1190,7 +1214,7 @@ module ActiveRecord
1190
1214
  def reset
1191
1215
  @future_result&.cancel
1192
1216
  @future_result = nil
1193
- @delegate_to_klass = false
1217
+ @delegate_to_model = false
1194
1218
  @to_sql = @arel = @loaded = @should_eager_load = nil
1195
1219
  @offsets = @take = nil
1196
1220
  @cache_keys = nil
@@ -1210,7 +1234,7 @@ module ActiveRecord
1210
1234
  relation.to_sql
1211
1235
  end
1212
1236
  else
1213
- klass.with_connection do |conn|
1237
+ model.with_connection do |conn|
1214
1238
  conn.unprepared_statement { conn.to_sql(arel) }
1215
1239
  end
1216
1240
  end
@@ -1220,12 +1244,12 @@ module ActiveRecord
1220
1244
  #
1221
1245
  # User.where(name: 'Oscar').where_values_hash
1222
1246
  # # => {name: "Oscar"}
1223
- def where_values_hash(relation_table_name = klass.table_name) # :nodoc:
1247
+ def where_values_hash(relation_table_name = model.table_name) # :nodoc:
1224
1248
  where_clause.to_h(relation_table_name)
1225
1249
  end
1226
1250
 
1227
1251
  def scope_for_create
1228
- hash = where_clause.to_h(klass.table_name, equality_only: true)
1252
+ hash = where_clause.to_h(model.table_name, equality_only: true)
1229
1253
  create_with_value.each { |k, v| hash[k.to_s] = v } unless create_with_value.empty?
1230
1254
  hash
1231
1255
  end
@@ -1271,6 +1295,10 @@ module ActiveRecord
1271
1295
  records.blank?
1272
1296
  end
1273
1297
 
1298
+ def readonly?
1299
+ readonly_value
1300
+ end
1301
+
1274
1302
  def values
1275
1303
  @values.dup
1276
1304
  end
@@ -1289,7 +1317,7 @@ module ActiveRecord
1289
1317
  end
1290
1318
 
1291
1319
  def empty_scope? # :nodoc:
1292
- @values == klass.unscoped.values
1320
+ @values == model.unscoped.values
1293
1321
  end
1294
1322
 
1295
1323
  def has_limit_or_offset? # :nodoc:
@@ -1297,7 +1325,7 @@ module ActiveRecord
1297
1325
  end
1298
1326
 
1299
1327
  def alias_tracker(joins = [], aliases = nil) # :nodoc:
1300
- ActiveRecord::Associations::AliasTracker.create(connection_pool, table.name, joins, aliases)
1328
+ ActiveRecord::Associations::AliasTracker.create(model.connection_pool, table.name, joins, aliases)
1301
1329
  end
1302
1330
 
1303
1331
  class StrictLoadingScope # :nodoc:
@@ -1327,46 +1355,46 @@ module ActiveRecord
1327
1355
 
1328
1356
  private
1329
1357
  def already_in_scope?(registry)
1330
- @delegate_to_klass && registry.current_scope(klass, true)
1358
+ @delegate_to_model && registry.current_scope(model, true)
1331
1359
  end
1332
1360
 
1333
1361
  def global_scope?(registry)
1334
- registry.global_current_scope(klass, true)
1362
+ registry.global_current_scope(model, true)
1335
1363
  end
1336
1364
 
1337
1365
  def current_scope_restoring_block(&block)
1338
- current_scope = klass.current_scope(true)
1366
+ current_scope = model.current_scope(true)
1339
1367
  -> record do
1340
- klass.current_scope = current_scope
1368
+ model.current_scope = current_scope
1341
1369
  yield record if block_given?
1342
1370
  end
1343
1371
  end
1344
1372
 
1345
1373
  def _new(attributes, &block)
1346
- klass.new(attributes, &block)
1374
+ model.new(attributes, &block)
1347
1375
  end
1348
1376
 
1349
1377
  def _create(attributes, &block)
1350
- klass.create(attributes, &block)
1378
+ model.create(attributes, &block)
1351
1379
  end
1352
1380
 
1353
1381
  def _create!(attributes, &block)
1354
- klass.create!(attributes, &block)
1382
+ model.create!(attributes, &block)
1355
1383
  end
1356
1384
 
1357
1385
  def _scoping(scope, registry, all_queries = false)
1358
- previous = registry.current_scope(klass, true)
1359
- registry.set_current_scope(klass, scope)
1386
+ previous = registry.current_scope(model, true)
1387
+ registry.set_current_scope(model, scope)
1360
1388
 
1361
1389
  if all_queries
1362
- previous_global = registry.global_current_scope(klass, true)
1363
- registry.set_global_current_scope(klass, scope)
1390
+ previous_global = registry.global_current_scope(model, true)
1391
+ registry.set_global_current_scope(model, scope)
1364
1392
  end
1365
1393
  yield
1366
1394
  ensure
1367
- registry.set_current_scope(klass, previous)
1395
+ registry.set_current_scope(model, previous)
1368
1396
  if all_queries
1369
- registry.set_global_current_scope(klass, previous_global)
1397
+ registry.set_global_current_scope(model, previous_global)
1370
1398
  end
1371
1399
  end
1372
1400
 
@@ -1378,7 +1406,7 @@ module ActiveRecord
1378
1406
  value = Arel::Nodes::Grouping.new(value)
1379
1407
  end
1380
1408
  else
1381
- type = klass.type_for_attribute(attr.name)
1409
+ type = model.type_for_attribute(attr.name)
1382
1410
  value = predicate_builder.build_bind_attribute(attr.name, type.cast(value))
1383
1411
  end
1384
1412
  [attr, value]
@@ -1387,12 +1415,16 @@ module ActiveRecord
1387
1415
 
1388
1416
  def _increment_attribute(attribute, value = 1)
1389
1417
  bind = predicate_builder.build_bind_attribute(attribute.name, value.abs)
1390
- expr = table.coalesce(Arel::Nodes::UnqualifiedColumn.new(attribute), 0)
1418
+ expr = table.coalesce(attribute, 0)
1391
1419
  expr = value < 0 ? expr - bind : expr + bind
1392
1420
  expr.expr
1393
1421
  end
1394
1422
 
1395
1423
  def exec_queries(&block)
1424
+ if lock_value && model.current_preventing_writes
1425
+ raise ActiveRecord::ReadOnlyError, "Lock query attempted while in readonly mode"
1426
+ end
1427
+
1396
1428
  skip_query_cache_if_necessary do
1397
1429
  rows = if scheduled?
1398
1430
  future = @future_result
@@ -1425,20 +1457,20 @@ module ActiveRecord
1425
1457
  if where_clause.contradiction?
1426
1458
  [].freeze
1427
1459
  elsif eager_loading?
1428
- klass.with_connection do |c|
1460
+ model.with_connection do |c|
1429
1461
  apply_join_dependency do |relation, join_dependency|
1430
1462
  if relation.null_relation?
1431
1463
  [].freeze
1432
1464
  else
1433
1465
  relation = join_dependency.apply_column_aliases(relation)
1434
1466
  @_join_dependency = join_dependency
1435
- c.select_all(relation.arel, "SQL", async: async)
1467
+ c.select_all(relation.arel, "#{model.name} Eager Load", async: async)
1436
1468
  end
1437
1469
  end
1438
1470
  end
1439
1471
  else
1440
- klass.with_connection do |c|
1441
- klass._query_by_sql(c, arel, async: async)
1472
+ model.with_connection do |c|
1473
+ model._query_by_sql(c, arel, async: async)
1442
1474
  end
1443
1475
  end
1444
1476
  end
@@ -1451,13 +1483,13 @@ module ActiveRecord
1451
1483
  @_join_dependency = nil
1452
1484
  records
1453
1485
  else
1454
- klass._load_from_sql(rows, &block).freeze
1486
+ model._load_from_sql(rows, &block).freeze
1455
1487
  end
1456
1488
  end
1457
1489
 
1458
1490
  def skip_query_cache_if_necessary(&block)
1459
1491
  if skip_query_cache_value
1460
- uncached(&block)
1492
+ model.uncached(&block)
1461
1493
  else
1462
1494
  yield
1463
1495
  end