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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +239 -878
- data/README.rdoc +1 -1
- data/lib/active_record/association_relation.rb +1 -0
- data/lib/active_record/associations/association.rb +34 -10
- data/lib/active_record/associations/builder/association.rb +7 -6
- data/lib/active_record/associations/collection_association.rb +10 -8
- data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +3 -2
- data/lib/active_record/associations/preloader/association.rb +2 -2
- data/lib/active_record/associations/singular_association.rb +8 -3
- data/lib/active_record/associations.rb +34 -4
- data/lib/active_record/asynchronous_queries_tracker.rb +28 -24
- data/lib/active_record/attribute_methods/primary_key.rb +2 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +2 -12
- data/lib/active_record/attribute_methods.rb +1 -1
- data/lib/active_record/autosave_association.rb +69 -27
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +16 -10
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +0 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +0 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +0 -9
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +90 -43
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +8 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +4 -5
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +7 -2
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +33 -6
- data/lib/active_record/connection_adapters/abstract/transaction.rb +15 -5
- data/lib/active_record/connection_adapters/abstract_adapter.rb +24 -26
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +21 -39
- data/lib/active_record/connection_adapters/mysql/quoting.rb +0 -8
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +2 -8
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +43 -45
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +42 -98
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -8
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -42
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +10 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -4
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +1 -11
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +6 -12
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +59 -16
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +45 -95
- data/lib/active_record/connection_adapters/schema_cache.rb +1 -3
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +76 -100
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +0 -6
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +13 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +8 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +53 -12
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +37 -67
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +0 -17
- data/lib/active_record/connection_adapters.rb +0 -56
- data/lib/active_record/connection_handling.rb +22 -0
- data/lib/active_record/core.rb +18 -14
- data/lib/active_record/database_configurations/database_config.rb +4 -0
- data/lib/active_record/database_configurations/hash_config.rb +8 -0
- data/lib/active_record/encryption/config.rb +3 -1
- data/lib/active_record/encryption/encryptable_record.rb +4 -4
- data/lib/active_record/encryption/encrypted_attribute_type.rb +10 -1
- data/lib/active_record/encryption/encryptor.rb +15 -8
- data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -2
- data/lib/active_record/encryption/scheme.rb +8 -1
- data/lib/active_record/enum.rb +9 -22
- data/lib/active_record/errors.rb +13 -5
- data/lib/active_record/fixtures.rb +0 -2
- data/lib/active_record/future_result.rb +14 -10
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/insert_all.rb +1 -1
- data/lib/active_record/locking/optimistic.rb +1 -1
- data/lib/active_record/log_subscriber.rb +5 -11
- data/lib/active_record/migration/command_recorder.rb +27 -10
- data/lib/active_record/migration/compatibility.rb +5 -2
- data/lib/active_record/migration.rb +35 -38
- data/lib/active_record/model_schema.rb +3 -4
- data/lib/active_record/nested_attributes.rb +4 -6
- data/lib/active_record/persistence.rb +128 -130
- data/lib/active_record/query_logs.rb +102 -50
- data/lib/active_record/query_logs_formatter.rb +17 -28
- data/lib/active_record/querying.rb +8 -8
- data/lib/active_record/railtie.rb +2 -26
- data/lib/active_record/railties/databases.rake +2 -17
- data/lib/active_record/reflection.rb +18 -21
- data/lib/active_record/relation/batches/batch_enumerator.rb +4 -3
- data/lib/active_record/relation/batches.rb +132 -72
- data/lib/active_record/relation/calculations.rb +40 -39
- data/lib/active_record/relation/delegation.rb +25 -14
- data/lib/active_record/relation/finder_methods.rb +18 -18
- data/lib/active_record/relation/merger.rb +8 -8
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -1
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +4 -3
- data/lib/active_record/relation/predicate_builder.rb +13 -0
- data/lib/active_record/relation/query_methods.rb +115 -65
- data/lib/active_record/relation/spawn_methods.rb +1 -1
- data/lib/active_record/relation.rb +79 -61
- data/lib/active_record/result.rb +66 -4
- data/lib/active_record/sanitization.rb +7 -6
- data/lib/active_record/schema_dumper.rb +5 -0
- data/lib/active_record/schema_migration.rb +2 -1
- data/lib/active_record/scoping/named.rb +5 -2
- data/lib/active_record/statement_cache.rb +12 -12
- data/lib/active_record/store.rb +7 -3
- data/lib/active_record/table_metadata.rb +1 -3
- data/lib/active_record/tasks/database_tasks.rb +48 -47
- data/lib/active_record/tasks/mysql_database_tasks.rb +0 -2
- data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -2
- data/lib/active_record/test_fixtures.rb +12 -0
- data/lib/active_record/token_for.rb +1 -1
- data/lib/active_record/validations/uniqueness.rb +8 -8
- data/lib/active_record.rb +15 -45
- data/lib/arel/collectors/bind.rb +1 -1
- data/lib/arel/table.rb +3 -7
- metadata +11 -12
- 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 =>
|
|
97
|
+
self.not(association => association_conditions)
|
|
97
98
|
else
|
|
98
|
-
self.not(reflection.table_name =>
|
|
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 =>
|
|
130
|
+
@scope.where!(association => association_conditions)
|
|
129
131
|
else
|
|
130
|
-
@scope.where!(reflection.table_name =>
|
|
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
|
-
|
|
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 `#{
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
700
|
-
|
|
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
|
-
|
|
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
|
-
|
|
717
|
-
|
|
718
|
-
|
|
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?(
|
|
1558
|
-
raise ArgumentError, "You must only pass a single or collection of #{
|
|
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
|
-
|
|
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 = [
|
|
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|
|
|
1634
|
+
key.map { |k| model.attribute_aliases[k.to_s] || k.to_s }
|
|
1613
1635
|
else
|
|
1614
1636
|
key = key.to_s
|
|
1615
|
-
|
|
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
|
|
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 ==
|
|
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
|
|
1889
|
-
arel.project(*
|
|
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[
|
|
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 =
|
|
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
|
|
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
|
-
|
|
1954
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
2192
|
-
|
|
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
|
-
|
|
2245
|
+
arel_column_with_table(table_name, column)
|
|
2202
2246
|
end
|
|
2203
2247
|
when String, Symbol
|
|
2204
|
-
arel_column(key
|
|
2205
|
-
|
|
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?(
|
|
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.
|