activerecord 7.2.2 → 8.0.0

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 (114) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +239 -878
  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 +10 -8
  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/preloader/association.rb +2 -2
  11. data/lib/active_record/associations/singular_association.rb +8 -3
  12. data/lib/active_record/associations.rb +34 -4
  13. data/lib/active_record/asynchronous_queries_tracker.rb +28 -24
  14. data/lib/active_record/attribute_methods/primary_key.rb +2 -7
  15. data/lib/active_record/attribute_methods/time_zone_conversion.rb +2 -12
  16. data/lib/active_record/attribute_methods.rb +1 -1
  17. data/lib/active_record/autosave_association.rb +69 -27
  18. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +16 -10
  19. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +0 -1
  20. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +0 -1
  21. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +0 -9
  22. data/lib/active_record/connection_adapters/abstract/database_statements.rb +90 -43
  23. data/lib/active_record/connection_adapters/abstract/query_cache.rb +8 -2
  24. data/lib/active_record/connection_adapters/abstract/quoting.rb +1 -1
  25. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +4 -5
  26. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +7 -2
  27. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +33 -6
  28. data/lib/active_record/connection_adapters/abstract/transaction.rb +15 -5
  29. data/lib/active_record/connection_adapters/abstract_adapter.rb +24 -26
  30. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +21 -39
  31. data/lib/active_record/connection_adapters/mysql/quoting.rb +0 -8
  32. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +2 -8
  33. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +43 -45
  34. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +42 -98
  35. data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -8
  36. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -42
  37. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
  38. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +10 -0
  39. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -4
  40. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +1 -11
  41. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +6 -12
  42. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +2 -1
  43. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +59 -16
  44. data/lib/active_record/connection_adapters/postgresql_adapter.rb +45 -95
  45. data/lib/active_record/connection_adapters/schema_cache.rb +1 -3
  46. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +76 -100
  47. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +0 -6
  48. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +13 -0
  49. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +8 -1
  50. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +53 -12
  51. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +37 -67
  52. data/lib/active_record/connection_adapters/trilogy_adapter.rb +0 -17
  53. data/lib/active_record/connection_adapters.rb +0 -56
  54. data/lib/active_record/connection_handling.rb +22 -0
  55. data/lib/active_record/core.rb +18 -14
  56. data/lib/active_record/database_configurations/database_config.rb +4 -0
  57. data/lib/active_record/database_configurations/hash_config.rb +8 -0
  58. data/lib/active_record/encryption/config.rb +3 -1
  59. data/lib/active_record/encryption/encryptable_record.rb +4 -4
  60. data/lib/active_record/encryption/encrypted_attribute_type.rb +10 -1
  61. data/lib/active_record/encryption/encryptor.rb +15 -8
  62. data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -2
  63. data/lib/active_record/encryption/scheme.rb +8 -1
  64. data/lib/active_record/enum.rb +9 -22
  65. data/lib/active_record/errors.rb +13 -5
  66. data/lib/active_record/fixtures.rb +0 -2
  67. data/lib/active_record/future_result.rb +14 -10
  68. data/lib/active_record/gem_version.rb +3 -3
  69. data/lib/active_record/insert_all.rb +1 -1
  70. data/lib/active_record/locking/optimistic.rb +1 -1
  71. data/lib/active_record/log_subscriber.rb +5 -11
  72. data/lib/active_record/migration/command_recorder.rb +27 -10
  73. data/lib/active_record/migration/compatibility.rb +5 -2
  74. data/lib/active_record/migration.rb +35 -38
  75. data/lib/active_record/model_schema.rb +3 -4
  76. data/lib/active_record/nested_attributes.rb +4 -6
  77. data/lib/active_record/persistence.rb +128 -130
  78. data/lib/active_record/query_logs.rb +102 -50
  79. data/lib/active_record/query_logs_formatter.rb +17 -28
  80. data/lib/active_record/querying.rb +8 -8
  81. data/lib/active_record/railtie.rb +2 -26
  82. data/lib/active_record/railties/databases.rake +2 -17
  83. data/lib/active_record/reflection.rb +18 -21
  84. data/lib/active_record/relation/batches/batch_enumerator.rb +4 -3
  85. data/lib/active_record/relation/batches.rb +132 -72
  86. data/lib/active_record/relation/calculations.rb +40 -39
  87. data/lib/active_record/relation/delegation.rb +25 -14
  88. data/lib/active_record/relation/finder_methods.rb +18 -18
  89. data/lib/active_record/relation/merger.rb +8 -8
  90. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -1
  91. data/lib/active_record/relation/predicate_builder/relation_handler.rb +4 -3
  92. data/lib/active_record/relation/predicate_builder.rb +13 -0
  93. data/lib/active_record/relation/query_methods.rb +115 -65
  94. data/lib/active_record/relation/spawn_methods.rb +1 -1
  95. data/lib/active_record/relation.rb +79 -61
  96. data/lib/active_record/result.rb +66 -4
  97. data/lib/active_record/sanitization.rb +7 -6
  98. data/lib/active_record/schema_dumper.rb +5 -0
  99. data/lib/active_record/schema_migration.rb +2 -1
  100. data/lib/active_record/scoping/named.rb +5 -2
  101. data/lib/active_record/statement_cache.rb +12 -12
  102. data/lib/active_record/store.rb +7 -3
  103. data/lib/active_record/table_metadata.rb +1 -3
  104. data/lib/active_record/tasks/database_tasks.rb +48 -47
  105. data/lib/active_record/tasks/mysql_database_tasks.rb +0 -2
  106. data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -2
  107. data/lib/active_record/test_fixtures.rb +12 -0
  108. data/lib/active_record/token_for.rb +1 -1
  109. data/lib/active_record/validations/uniqueness.rb +8 -8
  110. data/lib/active_record.rb +15 -45
  111. data/lib/arel/collectors/bind.rb +1 -1
  112. data/lib/arel/table.rb +3 -7
  113. metadata +11 -12
  114. data/lib/active_record/relation/record_fetch_warning.rb +0 -52
@@ -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,7 +498,8 @@ module ActiveRecord
491
498
 
492
499
  # Like #with, but modifies relation in place.
493
500
  def with!(*args) # :nodoc:
494
- self.with_values += args
501
+ args = process_with_args(args)
502
+ self.with_values |= args
495
503
  self
496
504
  end
497
505
 
@@ -499,7 +507,7 @@ module ActiveRecord
499
507
  #
500
508
  # Post.with_recursive(post_and_replies: [Post.where(id: 42), Post.joins('JOIN post_and_replies ON posts.in_reply_to_id = post_and_replies.id')])
501
509
  # # => ActiveRecord::Relation
502
- # # WITH post_and_replies AS (
510
+ # # WITH RECURSIVE post_and_replies AS (
503
511
  # # (SELECT * FROM posts WHERE id = 42)
504
512
  # # UNION ALL
505
513
  # # (SELECT * FROM posts JOIN posts_and_replies ON posts.in_reply_to_id = posts_and_replies.id)
@@ -514,7 +522,8 @@ module ActiveRecord
514
522
 
515
523
  # Like #with_recursive but modifies the relation in place.
516
524
  def with_recursive!(*args) # :nodoc:
517
- self.with_values += args
525
+ args = process_with_args(args)
526
+ self.with_values |= args
518
527
  @with_is_recursive = true
519
528
  self
520
529
  end
@@ -696,26 +705,39 @@ module ActiveRecord
696
705
  # # WHEN "conversations"."status" = 0 THEN 3
697
706
  # # END ASC
698
707
  #
699
- def in_order_of(column, values)
700
- klass.disallow_raw_sql!([column], permit: model.adapter_class.column_name_with_order_matcher)
708
+ # +filter+ can be set to +false+ to include all results instead of only the ones specified in +values+.
709
+ #
710
+ # Conversation.in_order_of(:status, [:archived, :active], filter: false)
711
+ # # SELECT "conversations".* FROM "conversations"
712
+ # # ORDER BY CASE
713
+ # # WHEN "conversations"."status" = 1 THEN 1
714
+ # # WHEN "conversations"."status" = 0 THEN 2
715
+ # # ELSE 3
716
+ # # END ASC
717
+ def in_order_of(column, values, filter: true)
718
+ model.disallow_raw_sql!([column], permit: model.adapter_class.column_name_with_order_matcher)
701
719
  return spawn.none! if values.empty?
702
720
 
703
721
  references = column_references([column])
704
722
  self.references_values |= references unless references.empty?
705
723
 
706
- values = values.map { |value| type_caster.type_cast_for_database(column, value) }
724
+ values = values.map { |value| model.type_caster.type_cast_for_database(column, value) }
707
725
  arel_column = column.is_a?(Arel::Nodes::SqlLiteral) ? column : order_column(column.to_s)
708
726
 
709
- where_clause =
710
- if values.include?(nil)
711
- arel_column.in(values.compact).or(arel_column.eq(nil))
712
- else
713
- arel_column.in(values)
714
- end
727
+ scope = spawn.order!(build_case_for_value_position(arel_column, values, filter: filter))
715
728
 
716
- spawn
717
- .order!(build_case_for_value_position(arel_column, values))
718
- .where!(where_clause)
729
+ if filter
730
+ where_clause =
731
+ if values.include?(nil)
732
+ arel_column.in(values.compact).or(arel_column.eq(nil))
733
+ else
734
+ arel_column.in(values)
735
+ end
736
+
737
+ scope = scope.where!(where_clause)
738
+ end
739
+
740
+ scope
719
741
  end
720
742
 
721
743
  # Replaces any existing order defined on the relation with the specified order.
@@ -1554,8 +1576,8 @@ module ActiveRecord
1554
1576
  records.flatten!(1)
1555
1577
  records.compact!
1556
1578
 
1557
- unless records.all?(klass) && relations.all? { |relation| relation.klass == klass }
1558
- raise ArgumentError, "You must only pass a single or collection of #{klass.name} objects to ##{__callee__}."
1579
+ unless records.all?(model) && relations.all? { |relation| relation.model == model }
1580
+ raise ArgumentError, "You must only pass a single or collection of #{model.name} objects to ##{__callee__}."
1559
1581
  end
1560
1582
 
1561
1583
  spawn.excluding!(records + relations.flat_map(&:ids))
@@ -1575,7 +1597,7 @@ module ActiveRecord
1575
1597
 
1576
1598
  def construct_join_dependency(associations, join_type) # :nodoc:
1577
1599
  ActiveRecord::Associations::JoinDependency.new(
1578
- klass, table, associations, join_type
1600
+ model, table, associations, join_type
1579
1601
  )
1580
1602
  end
1581
1603
 
@@ -1604,15 +1626,15 @@ module ActiveRecord
1604
1626
  elsif opts.include?("?")
1605
1627
  parts = [build_bound_sql_literal(opts, rest)]
1606
1628
  else
1607
- parts = [klass.sanitize_sql(rest.empty? ? opts : [opts, *rest])]
1629
+ parts = [model.sanitize_sql(rest.empty? ? opts : [opts, *rest])]
1608
1630
  end
1609
1631
  when Hash
1610
1632
  opts = opts.transform_keys do |key|
1611
1633
  if key.is_a?(Array)
1612
- key.map { |k| klass.attribute_aliases[k.to_s] || k.to_s }
1634
+ key.map { |k| model.attribute_aliases[k.to_s] || k.to_s }
1613
1635
  else
1614
1636
  key = key.to_s
1615
- klass.attribute_aliases[key] || key
1637
+ model.attribute_aliases[key] || key
1616
1638
  end
1617
1639
  end
1618
1640
  references = PredicateBuilder.references(opts)
@@ -1640,12 +1662,8 @@ module ActiveRecord
1640
1662
  def arel_columns(columns)
1641
1663
  columns.flat_map do |field|
1642
1664
  case field
1643
- when Symbol
1644
- arel_column(field.to_s) do |attr_name|
1645
- adapter_class.quote_table_name(attr_name)
1646
- end
1647
- when String
1648
- arel_column(field, &:itself)
1665
+ when Symbol, String
1666
+ arel_column(field)
1649
1667
  when Proc
1650
1668
  field.call
1651
1669
  when Hash
@@ -1828,7 +1846,7 @@ module ActiveRecord
1828
1846
 
1829
1847
  joins = joins_values.dup
1830
1848
  if joins.last.is_a?(ActiveRecord::Associations::JoinDependency)
1831
- stashed_eager_load = joins.pop if joins.last.base_klass == klass
1849
+ stashed_eager_load = joins.pop if joins.last.base_klass == model
1832
1850
  end
1833
1851
 
1834
1852
  joins.each_with_index do |join, i|
@@ -1885,8 +1903,8 @@ module ActiveRecord
1885
1903
  def build_select(arel)
1886
1904
  if select_values.any?
1887
1905
  arel.project(*arel_columns(select_values))
1888
- elsif klass.ignored_columns.any? || klass.enumerate_columns_in_select_statements
1889
- arel.project(*klass.column_names.map { |field| table[field] })
1906
+ elsif model.ignored_columns.any? || model.enumerate_columns_in_select_statements
1907
+ arel.project(*model.column_names.map { |field| table[field] })
1890
1908
  else
1891
1909
  arel.project(table[Arel.star])
1892
1910
  end
@@ -1896,8 +1914,6 @@ module ActiveRecord
1896
1914
  return if with_values.empty?
1897
1915
 
1898
1916
  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
1917
  build_with_value_from_hash(with_value)
1902
1918
  end
1903
1919
 
@@ -1939,29 +1955,60 @@ module ActiveRecord
1939
1955
  with_table = Arel::Table.new(name)
1940
1956
 
1941
1957
  table.join(with_table, kind).on(
1942
- with_table[klass.model_name.to_s.foreign_key].eq(table[klass.primary_key])
1958
+ with_table[model.model_name.to_s.foreign_key].eq(table[model.primary_key])
1943
1959
  ).join_sources.first
1944
1960
  end
1945
1961
 
1962
+ def arel_columns_from_hash(fields)
1963
+ fields.flat_map do |table_name, columns|
1964
+ table_name = table_name.name if table_name.is_a?(Symbol)
1965
+ case columns
1966
+ when Symbol, String
1967
+ arel_column_with_table(table_name, columns)
1968
+ when Array
1969
+ columns.map do |column|
1970
+ arel_column_with_table(table_name, column)
1971
+ end
1972
+ else
1973
+ raise TypeError, "Expected Symbol, String or Array, got: #{columns.class}"
1974
+ end
1975
+ end
1976
+ end
1977
+
1978
+ def arel_column_with_table(table_name, column_name)
1979
+ self.references_values |= [Arel.sql(table_name, retryable: true)]
1980
+
1981
+ if column_name.is_a?(Symbol) || !column_name.match?(/\W/)
1982
+ predicate_builder.resolve_arel_attribute(table_name, column_name) do
1983
+ lookup_table_klass_from_join_dependencies(table_name)
1984
+ end
1985
+ else
1986
+ Arel.sql("#{model.adapter_class.quote_table_name(table_name)}.#{column_name}")
1987
+ end
1988
+ end
1989
+
1946
1990
  def arel_column(field)
1947
- field = klass.attribute_aliases[field] || field
1991
+ field = field.name if is_symbol = field.is_a?(Symbol)
1992
+
1993
+ field = model.attribute_aliases[field] || field
1948
1994
  from = from_clause.name || from_clause.value
1949
1995
 
1950
- if klass.columns_hash.key?(field) && (!from || table_name_matches?(from))
1996
+ if model.columns_hash.key?(field) && (!from || table_name_matches?(from))
1951
1997
  table[field]
1952
1998
  elsif /\A(?<table>(?:\w+\.)?\w+)\.(?<column>\w+)\z/ =~ field
1953
- self.references_values |= [Arel.sql(table, retryable: true)]
1954
- predicate_builder.resolve_arel_attribute(table, column) do
1955
- lookup_table_klass_from_join_dependencies(table)
1956
- end
1957
- else
1999
+ arel_column_with_table(table, column)
2000
+ elsif block_given?
1958
2001
  yield field
2002
+ elsif Arel.arel_node?(field)
2003
+ field
2004
+ else
2005
+ Arel.sql(is_symbol ? model.adapter_class.quote_table_name(field) : field)
1959
2006
  end
1960
2007
  end
1961
2008
 
1962
2009
  def table_name_matches?(from)
1963
2010
  table_name = Regexp.escape(table.name)
1964
- quoted_table_name = Regexp.escape(adapter_class.quote_table_name(table.name))
2011
+ quoted_table_name = Regexp.escape(model.adapter_class.quote_table_name(table.name))
1965
2012
  /(?:\A|(?<!FROM)\s)(?:\b#{table_name}\b|#{quoted_table_name})(?!\.)/i.match?(from.to_s)
1966
2013
  end
1967
2014
 
@@ -2032,7 +2079,7 @@ module ActiveRecord
2032
2079
  end
2033
2080
 
2034
2081
  def preprocess_order_args(order_args)
2035
- @klass.disallow_raw_sql!(
2082
+ model.disallow_raw_sql!(
2036
2083
  flattened_args(order_args),
2037
2084
  permit: model.adapter_class.column_name_with_order_matcher
2038
2085
  )
@@ -2070,7 +2117,7 @@ module ActiveRecord
2070
2117
 
2071
2118
  def sanitize_order_arguments(order_args)
2072
2119
  order_args.map! do |arg|
2073
- klass.sanitize_sql_for_order(arg)
2120
+ model.sanitize_sql_for_order(arg)
2074
2121
  end
2075
2122
  end
2076
2123
 
@@ -2096,7 +2143,7 @@ module ActiveRecord
2096
2143
  arg.expr.relation.name
2097
2144
  end
2098
2145
  end
2099
- end.compact
2146
+ end.filter_map { |ref| Arel.sql(ref, retryable: true) if ref }
2100
2147
  end
2101
2148
 
2102
2149
  def extract_table_name_from(string)
@@ -2108,17 +2155,18 @@ module ActiveRecord
2108
2155
  if attr_name == "count" && !group_values.empty?
2109
2156
  table[attr_name]
2110
2157
  else
2111
- Arel.sql(adapter_class.quote_table_name(attr_name), retryable: true)
2158
+ Arel.sql(model.adapter_class.quote_table_name(attr_name), retryable: true)
2112
2159
  end
2113
2160
  end
2114
2161
  end
2115
2162
 
2116
- def build_case_for_value_position(column, values)
2163
+ def build_case_for_value_position(column, values, filter: true)
2117
2164
  node = Arel::Nodes::Case.new
2118
2165
  values.each.with_index(1) do |value, order|
2119
2166
  node.when(column.eq(value)).then(order)
2120
2167
  end
2121
2168
 
2169
+ node = node.else(values.length + 1) unless filter
2122
2170
  Arel::Nodes::Ascending.new(node)
2123
2171
  end
2124
2172
 
@@ -2176,38 +2224,40 @@ module ActiveRecord
2176
2224
  def process_select_args(fields)
2177
2225
  fields.flat_map do |field|
2178
2226
  if field.is_a?(Hash)
2179
- arel_columns_from_hash(field)
2227
+ arel_column_aliases_from_hash(field)
2180
2228
  else
2181
2229
  field
2182
2230
  end
2183
2231
  end
2184
2232
  end
2185
2233
 
2186
- def arel_columns_from_hash(fields)
2234
+ def arel_column_aliases_from_hash(fields)
2187
2235
  fields.flat_map do |key, columns_aliases|
2236
+ table_name = key.is_a?(Symbol) ? key.name : key
2188
2237
  case columns_aliases
2189
2238
  when Hash
2190
2239
  columns_aliases.map do |column, column_alias|
2191
- if values[:joins]&.include?(key)
2192
- references = PredicateBuilder.references({ key.to_s => fields[key] })
2193
- self.references_values |= references unless references.empty?
2194
- end
2195
- arel_column("#{key}.#{column}") do
2196
- predicate_builder.resolve_arel_attribute(key.to_s, column)
2197
- end.as(column_alias.to_s)
2240
+ arel_column_with_table(table_name, column)
2241
+ .as(model.adapter_class.quote_column_name(column_alias.to_s))
2198
2242
  end
2199
2243
  when Array
2200
2244
  columns_aliases.map do |column|
2201
- arel_column("#{key}.#{column}", &:itself)
2245
+ arel_column_with_table(table_name, column)
2202
2246
  end
2203
2247
  when String, Symbol
2204
- arel_column(key.to_s) do
2205
- predicate_builder.resolve_arel_attribute(klass.table_name, key.to_s)
2206
- end.as(columns_aliases.to_s)
2248
+ arel_column(key)
2249
+ .as(model.adapter_class.quote_column_name(columns_aliases.to_s))
2207
2250
  end
2208
2251
  end
2209
2252
  end
2210
2253
 
2254
+ def process_with_args(args)
2255
+ args.flat_map do |arg|
2256
+ raise ArgumentError, "Unsupported argument type: #{arg} #{arg.class}" unless arg.is_a?(Hash)
2257
+ arg.map { |k, v| { k => v } }
2258
+ end
2259
+ end
2260
+
2211
2261
  STRUCTURAL_VALUE_METHODS = (
2212
2262
  Relation::VALUE_METHODS -
2213
2263
  [:extending, :where, :having, :unscope, :references, :annotate, :optimizer_hints]
@@ -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.