activerecord 7.2.3.1 → 8.0.5.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +475 -946
- 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 +1 -1
- 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/join_dependency.rb +2 -2
- data/lib/active_record/associations/preloader/association.rb +2 -2
- data/lib/active_record/associations/preloader/batch.rb +7 -1
- 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 +4 -8
- data/lib/active_record/attribute_methods/query.rb +34 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +2 -12
- data/lib/active_record/autosave_association.rb +69 -27
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +34 -25
- 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 +8 -17
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +91 -44
- 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 +37 -10
- data/lib/active_record/connection_adapters/abstract/transaction.rb +15 -5
- data/lib/active_record/connection_adapters/abstract_adapter.rb +67 -74
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +21 -40
- 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 +50 -45
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +84 -94
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -8
- data/lib/active_record/connection_adapters/pool_config.rb +7 -7
- data/lib/active_record/connection_adapters/postgresql/column.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +72 -43
- 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 +53 -96
- data/lib/active_record/connection_adapters/schema_cache.rb +1 -3
- data/lib/active_record/connection_adapters/sqlite3/column.rb +8 -2
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +80 -100
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +0 -6
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +27 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +9 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +53 -12
- data/lib/active_record/connection_adapters/statement_pool.rb +4 -2
- 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 +23 -1
- data/lib/active_record/core.rb +29 -14
- data/lib/active_record/database_configurations/database_config.rb +4 -0
- data/lib/active_record/database_configurations/hash_config.rb +16 -2
- 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 +16 -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 +15 -9
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/insert_all.rb +3 -3
- 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 +32 -12
- data/lib/active_record/migration/compatibility.rb +5 -2
- data/lib/active_record/migration.rb +38 -42
- 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 +11 -35
- 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/array_handler.rb +3 -1
- 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 +105 -61
- data/lib/active_record/relation/spawn_methods.rb +7 -7
- data/lib/active_record/relation/where_clause.rb +1 -1
- data/lib/active_record/relation.rb +80 -62
- 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 +14 -14
- 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 +69 -60
- data/lib/active_record/tasks/mysql_database_tasks.rb +0 -2
- data/lib/active_record/tasks/postgresql_database_tasks.rb +2 -1
- data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -2
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +12 -0
- data/lib/active_record/token_for.rb +1 -1
- data/lib/active_record/transactions.rb +5 -6
- data/lib/active_record/type/serialized.rb +5 -0
- data/lib/active_record/validations/uniqueness.rb +8 -8
- data/lib/active_record.rb +21 -48
- data/lib/arel/collectors/bind.rb +2 -2
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +2 -2
- data/lib/arel/nodes/binary.rb +1 -1
- data/lib/arel/nodes/node.rb +1 -1
- data/lib/arel/nodes/sql_literal.rb +1 -1
- data/lib/arel/predications.rb +1 -3
- data/lib/arel/table.rb +3 -7
- metadata +10 -11
- 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
|
#
|
|
@@ -500,7 +507,7 @@ module ActiveRecord
|
|
|
500
507
|
#
|
|
501
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')])
|
|
502
509
|
# # => ActiveRecord::Relation
|
|
503
|
-
# # WITH post_and_replies AS (
|
|
510
|
+
# # WITH RECURSIVE post_and_replies AS (
|
|
504
511
|
# # (SELECT * FROM posts WHERE id = 42)
|
|
505
512
|
# # UNION ALL
|
|
506
513
|
# # (SELECT * FROM posts JOIN post_and_replies ON posts.in_reply_to_id = post_and_replies.id)
|
|
@@ -698,26 +705,39 @@ module ActiveRecord
|
|
|
698
705
|
# # WHEN "conversations"."status" = 0 THEN 3
|
|
699
706
|
# # END ASC
|
|
700
707
|
#
|
|
701
|
-
|
|
702
|
-
|
|
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)
|
|
703
719
|
return spawn.none! if values.empty?
|
|
704
720
|
|
|
705
721
|
references = column_references([column])
|
|
706
722
|
self.references_values |= references unless references.empty?
|
|
707
723
|
|
|
708
|
-
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) }
|
|
709
725
|
arel_column = column.is_a?(Arel::Nodes::SqlLiteral) ? column : order_column(column.to_s)
|
|
710
726
|
|
|
711
|
-
|
|
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
|
|
727
|
+
scope = spawn.order!(build_case_for_value_position(arel_column, values, filter: filter))
|
|
717
728
|
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
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
|
|
721
741
|
end
|
|
722
742
|
|
|
723
743
|
# Replaces any existing order defined on the relation with the specified order.
|
|
@@ -1556,8 +1576,8 @@ module ActiveRecord
|
|
|
1556
1576
|
records.flatten!(1)
|
|
1557
1577
|
records.compact!
|
|
1558
1578
|
|
|
1559
|
-
unless records.all?(
|
|
1560
|
-
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__}."
|
|
1561
1581
|
end
|
|
1562
1582
|
|
|
1563
1583
|
spawn.excluding!(records + relations.flat_map(&:ids))
|
|
@@ -1577,7 +1597,7 @@ module ActiveRecord
|
|
|
1577
1597
|
|
|
1578
1598
|
def construct_join_dependency(associations, join_type) # :nodoc:
|
|
1579
1599
|
ActiveRecord::Associations::JoinDependency.new(
|
|
1580
|
-
|
|
1600
|
+
model, table, associations, join_type
|
|
1581
1601
|
)
|
|
1582
1602
|
end
|
|
1583
1603
|
|
|
@@ -1606,15 +1626,15 @@ module ActiveRecord
|
|
|
1606
1626
|
elsif opts.include?("?")
|
|
1607
1627
|
parts = [build_bound_sql_literal(opts, rest)]
|
|
1608
1628
|
else
|
|
1609
|
-
parts = [
|
|
1629
|
+
parts = [model.sanitize_sql(rest.empty? ? opts : [opts, *rest])]
|
|
1610
1630
|
end
|
|
1611
1631
|
when Hash
|
|
1612
1632
|
opts = opts.transform_keys do |key|
|
|
1613
1633
|
if key.is_a?(Array)
|
|
1614
|
-
key.map { |k|
|
|
1634
|
+
key.map { |k| model.attribute_aliases[k.to_s] || k.to_s }
|
|
1615
1635
|
else
|
|
1616
1636
|
key = key.to_s
|
|
1617
|
-
|
|
1637
|
+
model.attribute_aliases[key] || key
|
|
1618
1638
|
end
|
|
1619
1639
|
end
|
|
1620
1640
|
references = PredicateBuilder.references(opts)
|
|
@@ -1642,12 +1662,8 @@ module ActiveRecord
|
|
|
1642
1662
|
def arel_columns(columns)
|
|
1643
1663
|
columns.flat_map do |field|
|
|
1644
1664
|
case field
|
|
1645
|
-
when Symbol
|
|
1646
|
-
arel_column(field
|
|
1647
|
-
adapter_class.quote_table_name(attr_name)
|
|
1648
|
-
end
|
|
1649
|
-
when String
|
|
1650
|
-
arel_column(field, &:itself)
|
|
1665
|
+
when Symbol, String
|
|
1666
|
+
arel_column(field)
|
|
1651
1667
|
when Proc
|
|
1652
1668
|
field.call
|
|
1653
1669
|
when Hash
|
|
@@ -1830,7 +1846,7 @@ module ActiveRecord
|
|
|
1830
1846
|
|
|
1831
1847
|
joins = joins_values.dup
|
|
1832
1848
|
if joins.last.is_a?(ActiveRecord::Associations::JoinDependency)
|
|
1833
|
-
stashed_eager_load = joins.pop if joins.last.base_klass ==
|
|
1849
|
+
stashed_eager_load = joins.pop if joins.last.base_klass == model
|
|
1834
1850
|
end
|
|
1835
1851
|
|
|
1836
1852
|
joins.each_with_index do |join, i|
|
|
@@ -1887,8 +1903,8 @@ module ActiveRecord
|
|
|
1887
1903
|
def build_select(arel)
|
|
1888
1904
|
if select_values.any?
|
|
1889
1905
|
arel.project(*arel_columns(select_values))
|
|
1890
|
-
elsif
|
|
1891
|
-
arel.project(*
|
|
1906
|
+
elsif model.ignored_columns.any? || model.enumerate_columns_in_select_statements
|
|
1907
|
+
arel.project(*model.column_names.map { |field| table[field] })
|
|
1892
1908
|
else
|
|
1893
1909
|
arel.project(table[Arel.star])
|
|
1894
1910
|
end
|
|
@@ -1912,7 +1928,8 @@ module ActiveRecord
|
|
|
1912
1928
|
|
|
1913
1929
|
def build_with_expression_from_value(value, nested = false)
|
|
1914
1930
|
case value
|
|
1915
|
-
when Arel::Nodes::SqlLiteral
|
|
1931
|
+
when Arel::Nodes::SqlLiteral, Arel::Nodes::BoundSqlLiteral
|
|
1932
|
+
Arel::Nodes::Grouping.new(value)
|
|
1916
1933
|
when ActiveRecord::Relation
|
|
1917
1934
|
if nested
|
|
1918
1935
|
value.arel.ast
|
|
@@ -1939,29 +1956,60 @@ module ActiveRecord
|
|
|
1939
1956
|
with_table = Arel::Table.new(name)
|
|
1940
1957
|
|
|
1941
1958
|
table.join(with_table, kind).on(
|
|
1942
|
-
with_table[
|
|
1959
|
+
with_table[model.model_name.to_s.foreign_key].eq(table[model.primary_key])
|
|
1943
1960
|
).join_sources.first
|
|
1944
1961
|
end
|
|
1945
1962
|
|
|
1963
|
+
def arel_columns_from_hash(fields)
|
|
1964
|
+
fields.flat_map do |table_name, columns|
|
|
1965
|
+
table_name = table_name.name if table_name.is_a?(Symbol)
|
|
1966
|
+
case columns
|
|
1967
|
+
when Symbol, String
|
|
1968
|
+
arel_column_with_table(table_name, columns)
|
|
1969
|
+
when Array
|
|
1970
|
+
columns.map do |column|
|
|
1971
|
+
arel_column_with_table(table_name, column)
|
|
1972
|
+
end
|
|
1973
|
+
else
|
|
1974
|
+
raise TypeError, "Expected Symbol, String or Array, got: #{columns.class}"
|
|
1975
|
+
end
|
|
1976
|
+
end
|
|
1977
|
+
end
|
|
1978
|
+
|
|
1979
|
+
def arel_column_with_table(table_name, column_name)
|
|
1980
|
+
self.references_values |= [Arel.sql(table_name, retryable: true)]
|
|
1981
|
+
|
|
1982
|
+
if column_name.is_a?(Symbol) || !column_name.match?(/\W/)
|
|
1983
|
+
predicate_builder.resolve_arel_attribute(table_name, column_name) do
|
|
1984
|
+
lookup_table_klass_from_join_dependencies(table_name)
|
|
1985
|
+
end
|
|
1986
|
+
else
|
|
1987
|
+
Arel.sql("#{model.adapter_class.quote_table_name(table_name)}.#{column_name}")
|
|
1988
|
+
end
|
|
1989
|
+
end
|
|
1990
|
+
|
|
1946
1991
|
def arel_column(field)
|
|
1947
|
-
field =
|
|
1992
|
+
field = field.name if is_symbol = field.is_a?(Symbol)
|
|
1993
|
+
|
|
1994
|
+
field = model.attribute_aliases[field] || field.to_s
|
|
1948
1995
|
from = from_clause.name || from_clause.value
|
|
1949
1996
|
|
|
1950
|
-
if
|
|
1997
|
+
if model.columns_hash.key?(field) && (!from || table_name_matches?(from))
|
|
1951
1998
|
table[field]
|
|
1952
1999
|
elsif /\A(?<table>(?:\w+\.)?\w+)\.(?<column>\w+)\z/ =~ field
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
lookup_table_klass_from_join_dependencies(table)
|
|
1956
|
-
end
|
|
1957
|
-
else
|
|
2000
|
+
arel_column_with_table(table, column)
|
|
2001
|
+
elsif block_given?
|
|
1958
2002
|
yield field
|
|
2003
|
+
elsif Arel.arel_node?(field)
|
|
2004
|
+
field
|
|
2005
|
+
else
|
|
2006
|
+
Arel.sql(is_symbol ? model.adapter_class.quote_table_name(field) : field)
|
|
1959
2007
|
end
|
|
1960
2008
|
end
|
|
1961
2009
|
|
|
1962
2010
|
def table_name_matches?(from)
|
|
1963
2011
|
table_name = Regexp.escape(table.name)
|
|
1964
|
-
quoted_table_name = Regexp.escape(adapter_class.quote_table_name(table.name))
|
|
2012
|
+
quoted_table_name = Regexp.escape(model.adapter_class.quote_table_name(table.name))
|
|
1965
2013
|
/(?:\A|(?<!FROM)\s)(?:\b#{table_name}\b|#{quoted_table_name})(?!\.)/i.match?(from.to_s)
|
|
1966
2014
|
end
|
|
1967
2015
|
|
|
@@ -2032,7 +2080,7 @@ module ActiveRecord
|
|
|
2032
2080
|
end
|
|
2033
2081
|
|
|
2034
2082
|
def preprocess_order_args(order_args)
|
|
2035
|
-
|
|
2083
|
+
model.disallow_raw_sql!(
|
|
2036
2084
|
flattened_args(order_args),
|
|
2037
2085
|
permit: model.adapter_class.column_name_with_order_matcher
|
|
2038
2086
|
)
|
|
@@ -2070,7 +2118,7 @@ module ActiveRecord
|
|
|
2070
2118
|
|
|
2071
2119
|
def sanitize_order_arguments(order_args)
|
|
2072
2120
|
order_args.map! do |arg|
|
|
2073
|
-
|
|
2121
|
+
model.sanitize_sql_for_order(arg)
|
|
2074
2122
|
end
|
|
2075
2123
|
end
|
|
2076
2124
|
|
|
@@ -2108,17 +2156,18 @@ module ActiveRecord
|
|
|
2108
2156
|
if attr_name == "count" && !group_values.empty?
|
|
2109
2157
|
table[attr_name]
|
|
2110
2158
|
else
|
|
2111
|
-
Arel.sql(adapter_class.quote_table_name(attr_name), retryable: true)
|
|
2159
|
+
Arel.sql(model.adapter_class.quote_table_name(attr_name), retryable: true)
|
|
2112
2160
|
end
|
|
2113
2161
|
end
|
|
2114
2162
|
end
|
|
2115
2163
|
|
|
2116
|
-
def build_case_for_value_position(column, values)
|
|
2164
|
+
def build_case_for_value_position(column, values, filter: true)
|
|
2117
2165
|
node = Arel::Nodes::Case.new
|
|
2118
2166
|
values.each.with_index(1) do |value, order|
|
|
2119
2167
|
node.when(column.eq(value)).then(order)
|
|
2120
2168
|
end
|
|
2121
2169
|
|
|
2170
|
+
node = node.else(values.length + 1) unless filter
|
|
2122
2171
|
Arel::Nodes::Ascending.new(node)
|
|
2123
2172
|
end
|
|
2124
2173
|
|
|
@@ -2176,34 +2225,29 @@ module ActiveRecord
|
|
|
2176
2225
|
def process_select_args(fields)
|
|
2177
2226
|
fields.flat_map do |field|
|
|
2178
2227
|
if field.is_a?(Hash)
|
|
2179
|
-
|
|
2228
|
+
arel_column_aliases_from_hash(field)
|
|
2180
2229
|
else
|
|
2181
2230
|
field
|
|
2182
2231
|
end
|
|
2183
2232
|
end
|
|
2184
2233
|
end
|
|
2185
2234
|
|
|
2186
|
-
def
|
|
2235
|
+
def arel_column_aliases_from_hash(fields)
|
|
2187
2236
|
fields.flat_map do |key, columns_aliases|
|
|
2237
|
+
table_name = key.is_a?(Symbol) ? key.name : key
|
|
2188
2238
|
case columns_aliases
|
|
2189
2239
|
when Hash
|
|
2190
2240
|
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)
|
|
2241
|
+
arel_column_with_table(table_name, column)
|
|
2242
|
+
.as(model.adapter_class.quote_column_name(column_alias.to_s))
|
|
2198
2243
|
end
|
|
2199
2244
|
when Array
|
|
2200
2245
|
columns_aliases.map do |column|
|
|
2201
|
-
|
|
2246
|
+
arel_column_with_table(table_name, column)
|
|
2202
2247
|
end
|
|
2203
2248
|
when String, Symbol
|
|
2204
|
-
arel_column(key
|
|
2205
|
-
|
|
2206
|
-
end.as(columns_aliases.to_s)
|
|
2249
|
+
arel_column(key)
|
|
2250
|
+
.as(model.adapter_class.quote_column_name(columns_aliases.to_s))
|
|
2207
2251
|
end
|
|
2208
2252
|
end
|
|
2209
2253
|
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?(
|
|
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.
|
|
@@ -52,18 +52,18 @@ module ActiveRecord
|
|
|
52
52
|
end
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
-
# Removes
|
|
55
|
+
# Removes the condition(s) specified in +skips+ from the query.
|
|
56
56
|
#
|
|
57
|
-
# Post.order('id asc').except(:order) #
|
|
58
|
-
# Post.where('id > 10').order('id asc').except(:where) #
|
|
57
|
+
# Post.order('id asc').except(:order) # removes the order condition
|
|
58
|
+
# Post.where('id > 10').order('id asc').except(:where) # removes the where condition but keeps the order
|
|
59
59
|
def except(*skips)
|
|
60
60
|
relation_with values.except(*skips)
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
-
#
|
|
63
|
+
# Keeps only the condition(s) specified in +onlies+ in the query, removing all others.
|
|
64
64
|
#
|
|
65
|
-
# Post.order('id asc').only(:where) #
|
|
66
|
-
# Post.order('id asc').only(:where, :order) #
|
|
65
|
+
# Post.order('id asc').only(:where) # keeps only the where condition, removes the order
|
|
66
|
+
# Post.order('id asc').only(:where, :order) # keeps only the where and order conditions
|
|
67
67
|
def only(*onlies)
|
|
68
68
|
relation_with values.slice(*onlies)
|
|
69
69
|
end
|
|
@@ -182,7 +182,7 @@ module ActiveRecord
|
|
|
182
182
|
non_attrs = columns.extract! { |node| node.is_a?(Arel::Predications) }
|
|
183
183
|
|
|
184
184
|
predicates.reject do |node|
|
|
185
|
-
if !non_attrs.empty? && node
|
|
185
|
+
if !non_attrs.empty? && equality_node?(node) && node.left.is_a?(Arel::Predications)
|
|
186
186
|
non_attrs.include?(node.left)
|
|
187
187
|
end || Arel.fetch_attribute(node) do |attr|
|
|
188
188
|
attrs.include?(attr) || columns.include?(attr.name.to_s)
|