activerecord 7.2.3 → 8.0.0.beta1

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.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (132) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +192 -1261
  3. data/README.rdoc +2 -2
  4. data/lib/active_record/associations/alias_tracker.rb +4 -6
  5. data/lib/active_record/associations/association.rb +25 -5
  6. data/lib/active_record/associations/belongs_to_association.rb +2 -18
  7. data/lib/active_record/associations/builder/association.rb +7 -6
  8. data/lib/active_record/associations/collection_association.rb +4 -4
  9. data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
  10. data/lib/active_record/associations/has_many_through_association.rb +4 -9
  11. data/lib/active_record/associations/join_dependency/join_association.rb +27 -25
  12. data/lib/active_record/associations/preloader/association.rb +2 -2
  13. data/lib/active_record/associations/singular_association.rb +8 -3
  14. data/lib/active_record/associations.rb +50 -32
  15. data/lib/active_record/asynchronous_queries_tracker.rb +28 -24
  16. data/lib/active_record/attribute_methods/serialization.rb +1 -1
  17. data/lib/active_record/attribute_methods.rb +19 -24
  18. data/lib/active_record/attributes.rb +26 -37
  19. data/lib/active_record/autosave_association.rb +81 -49
  20. data/lib/active_record/base.rb +2 -2
  21. data/lib/active_record/callbacks.rb +1 -1
  22. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +16 -10
  23. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +0 -1
  24. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +0 -1
  25. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +31 -75
  26. data/lib/active_record/connection_adapters/abstract/database_statements.rb +90 -43
  27. data/lib/active_record/connection_adapters/abstract/query_cache.rb +14 -19
  28. data/lib/active_record/connection_adapters/abstract/quoting.rb +1 -1
  29. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +2 -6
  30. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +27 -9
  31. data/lib/active_record/connection_adapters/abstract/transaction.rb +15 -5
  32. data/lib/active_record/connection_adapters/abstract_adapter.rb +27 -57
  33. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +28 -58
  34. data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -15
  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 +2 -16
  39. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -42
  40. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +10 -0
  41. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +0 -1
  42. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +12 -14
  43. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +1 -1
  44. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +51 -9
  45. data/lib/active_record/connection_adapters/postgresql_adapter.rb +44 -101
  46. data/lib/active_record/connection_adapters/schema_cache.rb +1 -3
  47. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +76 -100
  48. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +0 -13
  49. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +0 -6
  50. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +13 -0
  51. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +8 -2
  52. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +60 -22
  53. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +37 -67
  54. data/lib/active_record/connection_adapters/trilogy_adapter.rb +1 -18
  55. data/lib/active_record/connection_handling.rb +29 -11
  56. data/lib/active_record/core.rb +15 -60
  57. data/lib/active_record/counter_cache.rb +1 -1
  58. data/lib/active_record/database_configurations/connection_url_resolver.rb +1 -3
  59. data/lib/active_record/delegated_type.rb +18 -18
  60. data/lib/active_record/encryption/config.rb +3 -1
  61. data/lib/active_record/encryption/encryptable_record.rb +5 -5
  62. data/lib/active_record/encryption/encrypted_attribute_type.rb +11 -2
  63. data/lib/active_record/encryption/encryptor.rb +35 -29
  64. data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -2
  65. data/lib/active_record/encryption/scheme.rb +8 -1
  66. data/lib/active_record/enum.rb +12 -13
  67. data/lib/active_record/errors.rb +16 -8
  68. data/lib/active_record/fixture_set/table_row.rb +2 -19
  69. data/lib/active_record/fixtures.rb +0 -1
  70. data/lib/active_record/future_result.rb +14 -10
  71. data/lib/active_record/gem_version.rb +4 -4
  72. data/lib/active_record/insert_all.rb +1 -1
  73. data/lib/active_record/marshalling.rb +1 -4
  74. data/lib/active_record/migration/command_recorder.rb +22 -5
  75. data/lib/active_record/migration/compatibility.rb +5 -2
  76. data/lib/active_record/migration.rb +36 -35
  77. data/lib/active_record/model_schema.rb +1 -1
  78. data/lib/active_record/nested_attributes.rb +4 -6
  79. data/lib/active_record/persistence.rb +128 -130
  80. data/lib/active_record/query_cache.rb +5 -4
  81. data/lib/active_record/query_logs.rb +98 -44
  82. data/lib/active_record/query_logs_formatter.rb +17 -28
  83. data/lib/active_record/querying.rb +10 -10
  84. data/lib/active_record/railtie.rb +5 -6
  85. data/lib/active_record/railties/databases.rake +1 -2
  86. data/lib/active_record/reflection.rb +9 -7
  87. data/lib/active_record/relation/batches/batch_enumerator.rb +4 -3
  88. data/lib/active_record/relation/batches.rb +132 -72
  89. data/lib/active_record/relation/calculations.rb +55 -55
  90. data/lib/active_record/relation/delegation.rb +25 -14
  91. data/lib/active_record/relation/finder_methods.rb +31 -32
  92. data/lib/active_record/relation/merger.rb +8 -8
  93. data/lib/active_record/relation/predicate_builder/association_query_value.rb +0 -2
  94. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -1
  95. data/lib/active_record/relation/predicate_builder/relation_handler.rb +4 -3
  96. data/lib/active_record/relation/predicate_builder.rb +5 -0
  97. data/lib/active_record/relation/query_attribute.rb +1 -1
  98. data/lib/active_record/relation/query_methods.rb +90 -91
  99. data/lib/active_record/relation/record_fetch_warning.rb +2 -2
  100. data/lib/active_record/relation/spawn_methods.rb +1 -1
  101. data/lib/active_record/relation/where_clause.rb +2 -8
  102. data/lib/active_record/relation.rb +77 -76
  103. data/lib/active_record/result.rb +68 -7
  104. data/lib/active_record/sanitization.rb +7 -6
  105. data/lib/active_record/schema_dumper.rb +16 -29
  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/secure_token.rb +3 -3
  109. data/lib/active_record/signed_id.rb +6 -7
  110. data/lib/active_record/statement_cache.rb +12 -12
  111. data/lib/active_record/store.rb +7 -3
  112. data/lib/active_record/tasks/database_tasks.rb +24 -15
  113. data/lib/active_record/tasks/mysql_database_tasks.rb +0 -2
  114. data/lib/active_record/tasks/postgresql_database_tasks.rb +0 -7
  115. data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -2
  116. data/lib/active_record/test_fixtures.rb +12 -0
  117. data/lib/active_record/testing/query_assertions.rb +2 -2
  118. data/lib/active_record/token_for.rb +1 -1
  119. data/lib/active_record/transactions.rb +1 -3
  120. data/lib/active_record/validations/uniqueness.rb +8 -8
  121. data/lib/active_record.rb +16 -1
  122. data/lib/arel/collectors/bind.rb +1 -1
  123. data/lib/arel/crud.rb +0 -2
  124. data/lib/arel/delete_manager.rb +0 -5
  125. data/lib/arel/nodes/delete_statement.rb +2 -4
  126. data/lib/arel/nodes/update_statement.rb +2 -4
  127. data/lib/arel/select_manager.rb +2 -6
  128. data/lib/arel/update_manager.rb +0 -5
  129. data/lib/arel/visitors/dot.rb +0 -2
  130. data/lib/arel/visitors/sqlite.rb +0 -25
  131. data/lib/arel/visitors/to_sql.rb +1 -3
  132. metadata +14 -11
@@ -92,10 +92,11 @@ module ActiveRecord
92
92
  @scope.joins!(association)
93
93
  end
94
94
 
95
+ association_conditions = Array(reflection.association_primary_key).index_with(nil)
95
96
  if reflection.options[:class_name]
96
- self.not(association => { reflection.association_primary_key => nil })
97
+ self.not(association => association_conditions)
97
98
  else
98
- self.not(reflection.table_name => { reflection.association_primary_key => nil })
99
+ self.not(reflection.table_name => association_conditions)
99
100
  end
100
101
  end
101
102
 
@@ -124,10 +125,11 @@ module ActiveRecord
124
125
  associations.each do |association|
125
126
  reflection = scope_association_reflection(association)
126
127
  @scope.left_outer_joins!(association)
128
+ association_conditions = Array(reflection.association_primary_key).index_with(nil)
127
129
  if reflection.options[:class_name]
128
- @scope.where!(association => { reflection.association_primary_key => nil })
130
+ @scope.where!(association => association_conditions)
129
131
  else
130
- @scope.where!(reflection.table_name => { reflection.association_primary_key => nil })
132
+ @scope.where!(reflection.table_name => association_conditions)
131
133
  end
132
134
  end
133
135
 
@@ -136,9 +138,10 @@ module ActiveRecord
136
138
 
137
139
  private
138
140
  def scope_association_reflection(association)
139
- reflection = @scope.klass._reflect_on_association(association)
141
+ model = @scope.model
142
+ reflection = model._reflect_on_association(association)
140
143
  unless reflection
141
- raise ArgumentError.new("An association named `:#{association}` does not exist on the model `#{@scope.name}`.")
144
+ raise ArgumentError.new("An association named `:#{association}` does not exist on the model `#{model.name}`.")
142
145
  end
143
146
  reflection
144
147
  end
@@ -254,6 +257,10 @@ module ActiveRecord
254
257
  self
255
258
  end
256
259
 
260
+ def all # :nodoc:
261
+ spawn
262
+ end
263
+
257
264
  # Specify associations +args+ to be eager loaded using a <tt>LEFT OUTER JOIN</tt>.
258
265
  # Performs a single query joining all specified associations. For example:
259
266
  #
@@ -491,8 +498,7 @@ module ActiveRecord
491
498
 
492
499
  # Like #with, but modifies relation in place.
493
500
  def with!(*args) # :nodoc:
494
- args = process_with_args(args)
495
- self.with_values |= args
501
+ self.with_values += args
496
502
  self
497
503
  end
498
504
 
@@ -503,7 +509,7 @@ module ActiveRecord
503
509
  # # WITH post_and_replies AS (
504
510
  # # (SELECT * FROM posts WHERE id = 42)
505
511
  # # UNION ALL
506
- # # (SELECT * FROM posts JOIN post_and_replies ON posts.in_reply_to_id = post_and_replies.id)
512
+ # # (SELECT * FROM posts JOIN posts_and_replies ON posts.in_reply_to_id = posts_and_replies.id)
507
513
  # # )
508
514
  # # SELECT * FROM posts
509
515
  #
@@ -515,8 +521,7 @@ module ActiveRecord
515
521
 
516
522
  # Like #with_recursive but modifies the relation in place.
517
523
  def with_recursive!(*args) # :nodoc:
518
- args = process_with_args(args)
519
- self.with_values |= args
524
+ self.with_values += args
520
525
  @with_is_recursive = true
521
526
  self
522
527
  end
@@ -698,26 +703,39 @@ module ActiveRecord
698
703
  # # WHEN "conversations"."status" = 0 THEN 3
699
704
  # # END ASC
700
705
  #
701
- def in_order_of(column, values)
702
- klass.disallow_raw_sql!([column], permit: model.adapter_class.column_name_with_order_matcher)
706
+ # +filter+ can be set to +false+ to include all results instead of only the ones specified in +values+.
707
+ #
708
+ # Conversation.in_order_of(:status, [:archived, :active], filter: false)
709
+ # # SELECT "conversations".* FROM "conversations"
710
+ # # ORDER BY CASE
711
+ # # WHEN "conversations"."status" = 1 THEN 1
712
+ # # WHEN "conversations"."status" = 0 THEN 2
713
+ # # ELSE 3
714
+ # # END ASC
715
+ def in_order_of(column, values, filter: true)
716
+ model.disallow_raw_sql!([column], permit: model.adapter_class.column_name_with_order_matcher)
703
717
  return spawn.none! if values.empty?
704
718
 
705
719
  references = column_references([column])
706
720
  self.references_values |= references unless references.empty?
707
721
 
708
- values = values.map { |value| type_caster.type_cast_for_database(column, value) }
722
+ values = values.map { |value| model.type_caster.type_cast_for_database(column, value) }
709
723
  arel_column = column.is_a?(Arel::Nodes::SqlLiteral) ? column : order_column(column.to_s)
710
724
 
711
- where_clause =
712
- if values.include?(nil)
713
- arel_column.in(values.compact).or(arel_column.eq(nil))
714
- else
715
- arel_column.in(values)
716
- end
725
+ scope = spawn.order!(build_case_for_value_position(arel_column, values, filter: filter))
717
726
 
718
- spawn
719
- .order!(build_case_for_value_position(arel_column, values))
720
- .where!(where_clause)
727
+ if filter
728
+ where_clause =
729
+ if values.include?(nil)
730
+ arel_column.in(values.compact).or(arel_column.eq(nil))
731
+ else
732
+ arel_column.in(values)
733
+ end
734
+
735
+ scope = scope.where!(where_clause)
736
+ end
737
+
738
+ scope
721
739
  end
722
740
 
723
741
  # Replaces any existing order defined on the relation with the specified order.
@@ -1279,13 +1297,13 @@ module ActiveRecord
1279
1297
  #
1280
1298
  # users = User.readonly
1281
1299
  # users.first.save
1282
- # # => ActiveRecord::ReadOnlyRecord: User is marked as readonly
1300
+ # => ActiveRecord::ReadOnlyRecord: User is marked as readonly
1283
1301
  #
1284
1302
  # To make a readonly relation writable, pass +false+.
1285
1303
  #
1286
1304
  # users.readonly(false)
1287
1305
  # users.first.save
1288
- # # => true
1306
+ # => true
1289
1307
  def readonly(value = true)
1290
1308
  spawn.readonly!(value)
1291
1309
  end
@@ -1300,7 +1318,7 @@ module ActiveRecord
1300
1318
  #
1301
1319
  # user = User.strict_loading.first
1302
1320
  # user.comments.to_a
1303
- # # => ActiveRecord::StrictLoadingViolationError
1321
+ # => ActiveRecord::StrictLoadingViolationError
1304
1322
  def strict_loading(value = true)
1305
1323
  spawn.strict_loading!(value)
1306
1324
  end
@@ -1556,8 +1574,8 @@ module ActiveRecord
1556
1574
  records.flatten!(1)
1557
1575
  records.compact!
1558
1576
 
1559
- unless records.all?(klass) && relations.all? { |relation| relation.klass == klass }
1560
- raise ArgumentError, "You must only pass a single or collection of #{klass.name} objects to ##{__callee__}."
1577
+ unless records.all?(model) && relations.all? { |relation| relation.model == model }
1578
+ raise ArgumentError, "You must only pass a single or collection of #{model.name} objects to ##{__callee__}."
1561
1579
  end
1562
1580
 
1563
1581
  spawn.excluding!(records + relations.flat_map(&:ids))
@@ -1577,7 +1595,7 @@ module ActiveRecord
1577
1595
 
1578
1596
  def construct_join_dependency(associations, join_type) # :nodoc:
1579
1597
  ActiveRecord::Associations::JoinDependency.new(
1580
- klass, table, associations, join_type
1598
+ model, table, associations, join_type
1581
1599
  )
1582
1600
  end
1583
1601
 
@@ -1606,15 +1624,15 @@ module ActiveRecord
1606
1624
  elsif opts.include?("?")
1607
1625
  parts = [build_bound_sql_literal(opts, rest)]
1608
1626
  else
1609
- parts = [klass.sanitize_sql(rest.empty? ? opts : [opts, *rest])]
1627
+ parts = [model.sanitize_sql(rest.empty? ? opts : [opts, *rest])]
1610
1628
  end
1611
1629
  when Hash
1612
1630
  opts = opts.transform_keys do |key|
1613
1631
  if key.is_a?(Array)
1614
- key.map { |k| klass.attribute_aliases[k.to_s] || k.to_s }
1632
+ key.map { |k| model.attribute_aliases[k.to_s] || k.to_s }
1615
1633
  else
1616
1634
  key = key.to_s
1617
- klass.attribute_aliases[key] || key
1635
+ model.attribute_aliases[key] || key
1618
1636
  end
1619
1637
  end
1620
1638
  references = PredicateBuilder.references(opts)
@@ -1638,26 +1656,6 @@ module ActiveRecord
1638
1656
  self
1639
1657
  end
1640
1658
 
1641
- protected
1642
- def arel_columns(columns)
1643
- columns.flat_map do |field|
1644
- case field
1645
- when Symbol
1646
- arel_column(field.to_s) do |attr_name|
1647
- adapter_class.quote_table_name(attr_name)
1648
- end
1649
- when String
1650
- arel_column(field, &:itself)
1651
- when Proc
1652
- field.call
1653
- when Hash
1654
- arel_columns_from_hash(field)
1655
- else
1656
- field
1657
- end
1658
- end
1659
- end
1660
-
1661
1659
  private
1662
1660
  def async
1663
1661
  spawn.async!
@@ -1830,7 +1828,7 @@ module ActiveRecord
1830
1828
 
1831
1829
  joins = joins_values.dup
1832
1830
  if joins.last.is_a?(ActiveRecord::Associations::JoinDependency)
1833
- stashed_eager_load = joins.pop if joins.last.base_klass == klass
1831
+ stashed_eager_load = joins.pop if joins.last.base_klass == model
1834
1832
  end
1835
1833
 
1836
1834
  joins.each_with_index do |join, i|
@@ -1887,8 +1885,8 @@ module ActiveRecord
1887
1885
  def build_select(arel)
1888
1886
  if select_values.any?
1889
1887
  arel.project(*arel_columns(select_values))
1890
- elsif klass.ignored_columns.any? || klass.enumerate_columns_in_select_statements
1891
- arel.project(*klass.column_names.map { |field| table[field] })
1888
+ elsif model.ignored_columns.any? || model.enumerate_columns_in_select_statements
1889
+ arel.project(*model.column_names.map { |field| table[field] })
1892
1890
  else
1893
1891
  arel.project(table[Arel.star])
1894
1892
  end
@@ -1898,6 +1896,8 @@ module ActiveRecord
1898
1896
  return if with_values.empty?
1899
1897
 
1900
1898
  with_statements = with_values.map do |with_value|
1899
+ raise ArgumentError, "Unsupported argument type: #{with_value} #{with_value.class}" unless with_value.is_a?(Hash)
1900
+
1901
1901
  build_with_value_from_hash(with_value)
1902
1902
  end
1903
1903
 
@@ -1910,26 +1910,12 @@ module ActiveRecord
1910
1910
  end
1911
1911
  end
1912
1912
 
1913
- def build_with_expression_from_value(value, nested = false)
1913
+ def build_with_expression_from_value(value)
1914
1914
  case value
1915
1915
  when Arel::Nodes::SqlLiteral then Arel::Nodes::Grouping.new(value)
1916
- when ActiveRecord::Relation
1917
- if nested
1918
- value.arel.ast
1919
- else
1920
- value.arel
1921
- end
1916
+ when ActiveRecord::Relation then value.arel
1922
1917
  when Arel::SelectManager then value
1923
- when Array
1924
- return build_with_expression_from_value(value.first, false) if value.size == 1
1925
-
1926
- parts = value.map do |query|
1927
- build_with_expression_from_value(query, true)
1928
- end
1929
-
1930
- parts.reduce do |result, value|
1931
- Arel::Nodes::UnionAll.new(result, value)
1932
- end
1918
+ when Array then value.map { |q| build_with_expression_from_value(q) }.reduce { |result, value| result.union(:all, value) }
1933
1919
  else
1934
1920
  raise ArgumentError, "Unsupported argument type: `#{value}` #{value.class}"
1935
1921
  end
@@ -1939,18 +1925,37 @@ module ActiveRecord
1939
1925
  with_table = Arel::Table.new(name)
1940
1926
 
1941
1927
  table.join(with_table, kind).on(
1942
- with_table[klass.model_name.to_s.foreign_key].eq(table[klass.primary_key])
1928
+ with_table[model.model_name.to_s.foreign_key].eq(table[model.primary_key])
1943
1929
  ).join_sources.first
1944
1930
  end
1945
1931
 
1932
+ def arel_columns(columns)
1933
+ columns.flat_map do |field|
1934
+ case field
1935
+ when Symbol
1936
+ arel_column(field.to_s) do |attr_name|
1937
+ model.adapter_class.quote_table_name(attr_name)
1938
+ end
1939
+ when String
1940
+ arel_column(field, &:itself)
1941
+ when Proc
1942
+ field.call
1943
+ when Hash
1944
+ arel_columns_from_hash(field)
1945
+ else
1946
+ field
1947
+ end
1948
+ end
1949
+ end
1950
+
1946
1951
  def arel_column(field)
1947
- field = klass.attribute_aliases[field] || field
1952
+ field = model.attribute_aliases[field] || field
1948
1953
  from = from_clause.name || from_clause.value
1949
1954
 
1950
- if klass.columns_hash.key?(field) && (!from || table_name_matches?(from))
1955
+ if model.columns_hash.key?(field) && (!from || table_name_matches?(from))
1951
1956
  table[field]
1952
- elsif /\A(?<table>(?:\w+\.)?\w+)\.(?<column>\w+)\z/ =~ field
1953
- self.references_values |= [Arel.sql(table, retryable: true)]
1957
+ elsif field.match?(/\A\w+\.\w+\z/)
1958
+ table, column = field.split(".")
1954
1959
  predicate_builder.resolve_arel_attribute(table, column) do
1955
1960
  lookup_table_klass_from_join_dependencies(table)
1956
1961
  end
@@ -1961,7 +1966,7 @@ module ActiveRecord
1961
1966
 
1962
1967
  def table_name_matches?(from)
1963
1968
  table_name = Regexp.escape(table.name)
1964
- quoted_table_name = Regexp.escape(adapter_class.quote_table_name(table.name))
1969
+ quoted_table_name = Regexp.escape(model.adapter_class.quote_table_name(table.name))
1965
1970
  /(?:\A|(?<!FROM)\s)(?:\b#{table_name}\b|#{quoted_table_name})(?!\.)/i.match?(from.to_s)
1966
1971
  end
1967
1972
 
@@ -2032,7 +2037,7 @@ module ActiveRecord
2032
2037
  end
2033
2038
 
2034
2039
  def preprocess_order_args(order_args)
2035
- @klass.disallow_raw_sql!(
2040
+ model.disallow_raw_sql!(
2036
2041
  flattened_args(order_args),
2037
2042
  permit: model.adapter_class.column_name_with_order_matcher
2038
2043
  )
@@ -2070,7 +2075,7 @@ module ActiveRecord
2070
2075
 
2071
2076
  def sanitize_order_arguments(order_args)
2072
2077
  order_args.map! do |arg|
2073
- klass.sanitize_sql_for_order(arg)
2078
+ model.sanitize_sql_for_order(arg)
2074
2079
  end
2075
2080
  end
2076
2081
 
@@ -2096,7 +2101,7 @@ module ActiveRecord
2096
2101
  arg.expr.relation.name
2097
2102
  end
2098
2103
  end
2099
- end.filter_map { |ref| Arel.sql(ref, retryable: true) if ref }
2104
+ end.compact
2100
2105
  end
2101
2106
 
2102
2107
  def extract_table_name_from(string)
@@ -2108,17 +2113,18 @@ module ActiveRecord
2108
2113
  if attr_name == "count" && !group_values.empty?
2109
2114
  table[attr_name]
2110
2115
  else
2111
- Arel.sql(adapter_class.quote_table_name(attr_name), retryable: true)
2116
+ Arel.sql(model.adapter_class.quote_table_name(attr_name), retryable: true)
2112
2117
  end
2113
2118
  end
2114
2119
  end
2115
2120
 
2116
- def build_case_for_value_position(column, values)
2121
+ def build_case_for_value_position(column, values, filter: true)
2117
2122
  node = Arel::Nodes::Case.new
2118
2123
  values.each.with_index(1) do |value, order|
2119
2124
  node.when(column.eq(value)).then(order)
2120
2125
  end
2121
2126
 
2127
+ node = node.else(values.length + 1) unless filter
2122
2128
  Arel::Nodes::Ascending.new(node)
2123
2129
  end
2124
2130
 
@@ -2202,19 +2208,12 @@ module ActiveRecord
2202
2208
  end
2203
2209
  when String, Symbol
2204
2210
  arel_column(key.to_s) do
2205
- predicate_builder.resolve_arel_attribute(klass.table_name, key.to_s)
2211
+ predicate_builder.resolve_arel_attribute(model.table_name, key.to_s)
2206
2212
  end.as(columns_aliases.to_s)
2207
2213
  end
2208
2214
  end
2209
2215
  end
2210
2216
 
2211
- def process_with_args(args)
2212
- args.flat_map do |arg|
2213
- raise ArgumentError, "Unsupported argument type: #{arg} #{arg.class}" unless arg.is_a?(Hash)
2214
- arg.map { |k, v| { k => v } }
2215
- end
2216
- end
2217
-
2218
2217
  STRUCTURAL_VALUE_METHODS = (
2219
2218
  Relation::VALUE_METHODS -
2220
2219
  [:extending, :where, :having, :unscope, :references, :annotate, :optimizer_hints]
@@ -20,9 +20,9 @@ module ActiveRecord
20
20
  QueryRegistry.reset
21
21
 
22
22
  super.tap do |records|
23
- if logger && ActiveRecord.warn_on_records_fetched_greater_than
23
+ if model.logger && ActiveRecord.warn_on_records_fetched_greater_than
24
24
  if records.length > ActiveRecord.warn_on_records_fetched_greater_than
25
- logger.warn "Query fetched #{records.size} #{@klass} records: #{QueryRegistry.queries.join(";")}"
25
+ model.logger.warn "Query fetched #{records.size} #{@klass} records: #{QueryRegistry.queries.join(";")}"
26
26
  end
27
27
  end
28
28
  end
@@ -7,7 +7,7 @@ require "active_record/relation/merger"
7
7
  module ActiveRecord
8
8
  module SpawnMethods
9
9
  def spawn # :nodoc:
10
- already_in_scope?(klass.scope_registry) ? klass.all : clone
10
+ already_in_scope?(model.scope_registry) ? model.all : clone
11
11
  end
12
12
 
13
13
  # Merges in the conditions from <tt>other</tt>, if <tt>other</tt> is an ActiveRecord::Relation.
@@ -135,14 +135,10 @@ module ActiveRecord
135
135
 
136
136
  def extract_attribute(node)
137
137
  attr_node = nil
138
-
139
- valid_attrs = Arel.fetch_attribute(node) do |attr|
140
- !attr_node || attr_node == attr # all attr nodes should be the same
141
- ensure
138
+ Arel.fetch_attribute(node) do |attr|
139
+ return if attr_node&.!= attr # all attr nodes should be the same
142
140
  attr_node = attr
143
141
  end
144
- return unless valid_attrs # all nested nodes should yield an attribute
145
-
146
142
  attr_node
147
143
  end
148
144
 
@@ -176,8 +172,6 @@ module ActiveRecord
176
172
  end
177
173
 
178
174
  def except_predicates(columns)
179
- return predicates if columns.empty?
180
-
181
175
  attrs = columns.extract! { |node| node.is_a?(Arel::Attribute) }
182
176
  non_attrs = columns.extract! { |node| node.is_a?(Arel::Predications) }
183
177