activerecord 7.2.4 → 8.1.4
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 +1013 -878
- data/README.rdoc +1 -1
- data/lib/active_record/association_relation.rb +2 -1
- data/lib/active_record/associations/association.rb +69 -27
- data/lib/active_record/associations/association_scope.rb +1 -1
- data/lib/active_record/associations/belongs_to_association.rb +2 -2
- data/lib/active_record/associations/builder/association.rb +23 -11
- data/lib/active_record/associations/builder/belongs_to.rb +36 -8
- data/lib/active_record/associations/builder/collection_association.rb +7 -3
- data/lib/active_record/associations/builder/has_one.rb +1 -1
- data/lib/active_record/associations/builder/singular_association.rb +33 -5
- data/lib/active_record/associations/collection_association.rb +7 -3
- data/lib/active_record/associations/collection_proxy.rb +26 -4
- data/lib/active_record/associations/deprecation.rb +88 -0
- data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
- data/lib/active_record/associations/errors.rb +3 -0
- data/lib/active_record/associations/foreign_association.rb +3 -1
- data/lib/active_record/associations/has_many_through_association.rb +3 -2
- data/lib/active_record/associations/has_one_association.rb +1 -0
- data/lib/active_record/associations/join_dependency.rb +3 -2
- data/lib/active_record/associations/preloader/association.rb +3 -3
- data/lib/active_record/associations/preloader/batch.rb +7 -1
- data/lib/active_record/associations/preloader/branch.rb +1 -0
- data/lib/active_record/associations/singular_association.rb +8 -3
- data/lib/active_record/associations.rb +192 -24
- 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/serialization.rb +18 -5
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -14
- data/lib/active_record/attributes.rb +3 -0
- data/lib/active_record/autosave_association.rb +69 -27
- data/lib/active_record/base.rb +1 -2
- data/lib/active_record/callbacks.rb +1 -2
- data/lib/active_record/coders/column_serializer.rb +1 -1
- data/lib/active_record/coders/json.rb +16 -6
- data/lib/active_record/coders/yaml_column.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +35 -28
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +16 -4
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +68 -13
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +429 -93
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +148 -74
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +27 -5
- data/lib/active_record/connection_adapters/abstract/quoting.rb +16 -25
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +11 -7
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +32 -35
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +124 -34
- data/lib/active_record/connection_adapters/abstract/transaction.rb +40 -8
- data/lib/active_record/connection_adapters/abstract_adapter.rb +129 -63
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +132 -65
- data/lib/active_record/connection_adapters/column.rb +14 -4
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +4 -4
- data/lib/active_record/connection_adapters/mysql/quoting.rb +0 -8
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +41 -10
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +79 -66
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +89 -94
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +2 -10
- data/lib/active_record/connection_adapters/pool_config.rb +7 -7
- data/lib/active_record/connection_adapters/postgresql/column.rb +8 -2
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +79 -61
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +10 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +46 -3
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +21 -10
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -4
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +9 -17
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +14 -33
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +71 -32
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +156 -68
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +78 -105
- 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 +90 -98
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +0 -8
- 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 +15 -16
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +104 -37
- data/lib/active_record/connection_adapters/statement_pool.rb +4 -2
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +41 -66
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +15 -18
- data/lib/active_record/connection_adapters.rb +1 -56
- data/lib/active_record/connection_handling.rb +25 -2
- data/lib/active_record/core.rb +33 -17
- data/lib/active_record/counter_cache.rb +35 -8
- data/lib/active_record/database_configurations/database_config.rb +9 -1
- data/lib/active_record/database_configurations/hash_config.rb +74 -9
- data/lib/active_record/database_configurations/url_config.rb +15 -3
- data/lib/active_record/database_configurations.rb +7 -3
- data/lib/active_record/delegated_type.rb +1 -1
- data/lib/active_record/disable_joins_association_relation.rb +5 -1
- data/lib/active_record/dynamic_matchers.rb +54 -69
- data/lib/active_record/encryption/config.rb +3 -1
- data/lib/active_record/encryption/encryptable_record.rb +8 -8
- data/lib/active_record/encryption/encrypted_attribute_type.rb +11 -2
- data/lib/active_record/encryption/encrypted_fixtures.rb +12 -7
- data/lib/active_record/encryption/encryptor.rb +28 -8
- data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -2
- data/lib/active_record/encryption/scheme.rb +9 -2
- data/lib/active_record/enum.rb +33 -30
- data/lib/active_record/errors.rb +33 -9
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/explain_registry.rb +51 -2
- data/lib/active_record/filter_attribute_handler.rb +76 -0
- data/lib/active_record/fixtures.rb +2 -4
- data/lib/active_record/future_result.rb +15 -9
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/inheritance.rb +9 -4
- data/lib/active_record/insert_all.rb +14 -9
- data/lib/active_record/locking/optimistic.rb +8 -1
- data/lib/active_record/locking/pessimistic.rb +5 -0
- data/lib/active_record/log_subscriber.rb +31 -29
- data/lib/active_record/message_pack.rb +13 -0
- data/lib/active_record/middleware/shard_selector.rb +34 -17
- data/lib/active_record/migration/command_recorder.rb +56 -13
- data/lib/active_record/migration/compatibility.rb +37 -24
- data/lib/active_record/migration/default_schema_versions_formatter.rb +30 -0
- data/lib/active_record/migration.rb +48 -42
- data/lib/active_record/model_schema.rb +40 -15
- data/lib/active_record/nested_attributes.rb +14 -12
- data/lib/active_record/persistence.rb +163 -133
- data/lib/active_record/query_cache.rb +22 -15
- data/lib/active_record/query_logs.rb +100 -52
- data/lib/active_record/query_logs_formatter.rb +17 -28
- data/lib/active_record/querying.rb +21 -9
- data/lib/active_record/railtie.rb +35 -30
- data/lib/active_record/railties/controller_runtime.rb +11 -6
- data/lib/active_record/railties/databases.rake +26 -38
- data/lib/active_record/railties/job_checkpoints.rb +15 -0
- data/lib/active_record/railties/job_runtime.rb +10 -11
- data/lib/active_record/reflection.rb +54 -22
- data/lib/active_record/relation/batches/batch_enumerator.rb +4 -3
- data/lib/active_record/relation/batches.rb +147 -73
- data/lib/active_record/relation/calculations.rb +60 -43
- data/lib/active_record/relation/delegation.rb +25 -15
- data/lib/active_record/relation/finder_methods.rb +73 -43
- data/lib/active_record/relation/merger.rb +12 -10
- data/lib/active_record/relation/predicate_builder/array_handler.rb +3 -1
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +9 -9
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +8 -8
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +4 -3
- data/lib/active_record/relation/predicate_builder.rb +23 -8
- data/lib/active_record/relation/query_attribute.rb +3 -1
- data/lib/active_record/relation/query_methods.rb +200 -96
- data/lib/active_record/relation/spawn_methods.rb +7 -7
- data/lib/active_record/relation/where_clause.rb +2 -9
- data/lib/active_record/relation.rb +127 -87
- data/lib/active_record/result.rb +109 -24
- data/lib/active_record/runtime_registry.rb +42 -58
- data/lib/active_record/sanitization.rb +9 -6
- data/lib/active_record/schema.rb +1 -1
- data/lib/active_record/schema_dumper.rb +17 -10
- data/lib/active_record/schema_migration.rb +2 -1
- data/lib/active_record/scoping/named.rb +5 -2
- data/lib/active_record/scoping.rb +0 -1
- data/lib/active_record/signed_id.rb +44 -16
- data/lib/active_record/statement_cache.rb +24 -20
- data/lib/active_record/store.rb +53 -22
- data/lib/active_record/structured_event_subscriber.rb +85 -0
- data/lib/active_record/table_metadata.rb +6 -23
- data/lib/active_record/tasks/abstract_tasks.rb +83 -0
- data/lib/active_record/tasks/database_tasks.rb +85 -85
- data/lib/active_record/tasks/mysql_database_tasks.rb +4 -58
- data/lib/active_record/tasks/postgresql_database_tasks.rb +7 -40
- data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -28
- data/lib/active_record/test_databases.rb +18 -4
- data/lib/active_record/test_fixtures.rb +52 -6
- data/lib/active_record/testing/query_assertions.rb +8 -2
- data/lib/active_record/timestamp.rb +4 -2
- data/lib/active_record/token_for.rb +1 -1
- data/lib/active_record/transaction.rb +2 -5
- data/lib/active_record/transactions.rb +56 -32
- data/lib/active_record/type/hash_lookup_type_map.rb +2 -1
- data/lib/active_record/type/internal/timezone.rb +7 -0
- data/lib/active_record/type/json.rb +13 -2
- data/lib/active_record/type/serialized.rb +16 -4
- data/lib/active_record/type/type_map.rb +1 -1
- data/lib/active_record/type_caster/connection.rb +2 -1
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record/validations/uniqueness.rb +8 -8
- data/lib/active_record.rb +85 -50
- data/lib/arel/alias_predication.rb +2 -0
- 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/crud.rb +6 -11
- data/lib/arel/nodes/binary.rb +1 -1
- data/lib/arel/nodes/count.rb +2 -2
- data/lib/arel/nodes/function.rb +4 -10
- data/lib/arel/nodes/named_function.rb +2 -2
- data/lib/arel/nodes/node.rb +2 -2
- data/lib/arel/nodes/sql_literal.rb +1 -1
- data/lib/arel/nodes.rb +0 -2
- data/lib/arel/predications.rb +1 -3
- data/lib/arel/select_manager.rb +7 -2
- data/lib/arel/table.rb +3 -7
- data/lib/arel/visitors/dot.rb +0 -3
- data/lib/arel/visitors/postgresql.rb +55 -0
- data/lib/arel/visitors/sqlite.rb +55 -8
- data/lib/arel/visitors/to_sql.rb +4 -22
- data/lib/arel.rb +3 -1
- data/lib/rails/generators/active_record/application_record/USAGE +1 -1
- metadata +15 -12
- data/lib/active_record/explain_subscriber.rb +0 -34
- data/lib/active_record/normalization.rb +0 -163
- 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)
|
|
@@ -569,7 +576,7 @@ module ActiveRecord
|
|
|
569
576
|
end
|
|
570
577
|
|
|
571
578
|
def group!(*args) # :nodoc:
|
|
572
|
-
self.group_values
|
|
579
|
+
self.group_values |= args
|
|
573
580
|
self
|
|
574
581
|
end
|
|
575
582
|
|
|
@@ -698,26 +705,47 @@ 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
|
-
|
|
709
|
-
|
|
724
|
+
if column.is_a?(Arel::Nodes::SqlLiteral)
|
|
725
|
+
arel_column = column
|
|
726
|
+
else
|
|
727
|
+
arel_column = order_column(column.to_s)
|
|
710
728
|
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
arel_column.in(values.compact).or(arel_column.eq(nil))
|
|
714
|
-
else
|
|
715
|
-
arel_column.in(values)
|
|
729
|
+
unless arel_column.is_a?(Arel::Nodes::SqlLiteral)
|
|
730
|
+
values = cast_values_for_in_order_of(values, arel_column.type_caster)
|
|
716
731
|
end
|
|
732
|
+
return spawn.none! if values.empty?
|
|
733
|
+
end
|
|
717
734
|
|
|
718
|
-
spawn
|
|
719
|
-
|
|
720
|
-
|
|
735
|
+
scope = spawn.order!(build_case_for_value_position(arel_column, values, filter: filter))
|
|
736
|
+
|
|
737
|
+
if filter
|
|
738
|
+
where_clause =
|
|
739
|
+
if values.include?(nil)
|
|
740
|
+
arel_column.in(values.compact).or(arel_column.eq(nil))
|
|
741
|
+
else
|
|
742
|
+
arel_column.in(values)
|
|
743
|
+
end
|
|
744
|
+
|
|
745
|
+
scope = scope.where!(where_clause)
|
|
746
|
+
end
|
|
747
|
+
|
|
748
|
+
scope
|
|
721
749
|
end
|
|
722
750
|
|
|
723
751
|
# Replaces any existing order defined on the relation with the specified order.
|
|
@@ -789,7 +817,7 @@ module ActiveRecord
|
|
|
789
817
|
end
|
|
790
818
|
|
|
791
819
|
def unscope!(*args) # :nodoc:
|
|
792
|
-
self.unscope_values
|
|
820
|
+
self.unscope_values |= args
|
|
793
821
|
|
|
794
822
|
args.each do |scope|
|
|
795
823
|
case scope
|
|
@@ -817,6 +845,26 @@ module ActiveRecord
|
|
|
817
845
|
self
|
|
818
846
|
end
|
|
819
847
|
|
|
848
|
+
def table_name_qualified_unscope_values
|
|
849
|
+
self.unscope_values.map do |scope|
|
|
850
|
+
case scope
|
|
851
|
+
when Hash
|
|
852
|
+
scope.transform_values do |target_value|
|
|
853
|
+
case target_value
|
|
854
|
+
when Array
|
|
855
|
+
target_value.map { |value| qualify_attribute_with_table_name(value) }
|
|
856
|
+
when Symbol, String
|
|
857
|
+
qualify_attribute_with_table_name(target_value)
|
|
858
|
+
else
|
|
859
|
+
target_value
|
|
860
|
+
end
|
|
861
|
+
end
|
|
862
|
+
else
|
|
863
|
+
scope
|
|
864
|
+
end
|
|
865
|
+
end
|
|
866
|
+
end
|
|
867
|
+
|
|
820
868
|
# Performs JOINs on +args+. The given symbol(s) should match the name of
|
|
821
869
|
# the association(s).
|
|
822
870
|
#
|
|
@@ -1028,13 +1076,13 @@ module ActiveRecord
|
|
|
1028
1076
|
# Allows you to change a previously set where condition for a given attribute, instead of appending to that condition.
|
|
1029
1077
|
#
|
|
1030
1078
|
# Post.where(trashed: true).where(trashed: false)
|
|
1031
|
-
# # WHERE `trashed` =
|
|
1079
|
+
# # WHERE `trashed` = true AND `trashed` = false
|
|
1032
1080
|
#
|
|
1033
1081
|
# Post.where(trashed: true).rewhere(trashed: false)
|
|
1034
|
-
# # WHERE `trashed` =
|
|
1082
|
+
# # WHERE `trashed` = false
|
|
1035
1083
|
#
|
|
1036
1084
|
# Post.where(active: true).where(trashed: true).rewhere(trashed: false)
|
|
1037
|
-
# # WHERE `active` =
|
|
1085
|
+
# # WHERE `active` = true AND `trashed` = false
|
|
1038
1086
|
#
|
|
1039
1087
|
# This is short-hand for <tt>unscope(where: conditions.keys).where(conditions)</tt>.
|
|
1040
1088
|
# Note that unlike reorder, we're only unscoping the named conditions -- not the entire where statement.
|
|
@@ -1056,16 +1104,16 @@ module ActiveRecord
|
|
|
1056
1104
|
# end
|
|
1057
1105
|
#
|
|
1058
1106
|
# User.where(accepted: true)
|
|
1059
|
-
# # WHERE `accepted` =
|
|
1107
|
+
# # WHERE `accepted` = true
|
|
1060
1108
|
#
|
|
1061
1109
|
# User.where(accepted: true).invert_where
|
|
1062
|
-
# # WHERE `accepted` !=
|
|
1110
|
+
# # WHERE `accepted` != true
|
|
1063
1111
|
#
|
|
1064
1112
|
# User.active
|
|
1065
|
-
# # WHERE `accepted` =
|
|
1113
|
+
# # WHERE `accepted` = true AND `locked` = false
|
|
1066
1114
|
#
|
|
1067
1115
|
# User.active.invert_where
|
|
1068
|
-
# # WHERE NOT (`accepted` =
|
|
1116
|
+
# # WHERE NOT (`accepted` = true AND `locked` = false)
|
|
1069
1117
|
#
|
|
1070
1118
|
# Be careful because this inverts all conditions before +invert_where+ call.
|
|
1071
1119
|
#
|
|
@@ -1076,7 +1124,7 @@ module ActiveRecord
|
|
|
1076
1124
|
#
|
|
1077
1125
|
# # It also inverts `where(role: 'admin')` unexpectedly.
|
|
1078
1126
|
# User.where(role: 'admin').inactive
|
|
1079
|
-
# # WHERE NOT (`role` = 'admin' AND `accepted` =
|
|
1127
|
+
# # WHERE NOT (`role` = 'admin' AND `accepted` = true AND `locked` = false)
|
|
1080
1128
|
#
|
|
1081
1129
|
def invert_where
|
|
1082
1130
|
spawn.invert_where!
|
|
@@ -1193,6 +1241,7 @@ module ActiveRecord
|
|
|
1193
1241
|
end
|
|
1194
1242
|
|
|
1195
1243
|
def limit!(value) # :nodoc:
|
|
1244
|
+
value = Integer(value) unless value.nil?
|
|
1196
1245
|
self.limit_value = value
|
|
1197
1246
|
self
|
|
1198
1247
|
end
|
|
@@ -1445,7 +1494,7 @@ module ActiveRecord
|
|
|
1445
1494
|
modules << Module.new(&block) if block
|
|
1446
1495
|
modules.flatten!
|
|
1447
1496
|
|
|
1448
|
-
self.extending_values
|
|
1497
|
+
self.extending_values |= modules
|
|
1449
1498
|
extend(*extending_values) if extending_values.any?
|
|
1450
1499
|
|
|
1451
1500
|
self
|
|
@@ -1513,7 +1562,7 @@ module ActiveRecord
|
|
|
1513
1562
|
|
|
1514
1563
|
# Like #annotate, but modifies relation in place.
|
|
1515
1564
|
def annotate!(*args) # :nodoc:
|
|
1516
|
-
self.annotate_values
|
|
1565
|
+
self.annotate_values |= args
|
|
1517
1566
|
self
|
|
1518
1567
|
end
|
|
1519
1568
|
|
|
@@ -1556,8 +1605,8 @@ module ActiveRecord
|
|
|
1556
1605
|
records.flatten!(1)
|
|
1557
1606
|
records.compact!
|
|
1558
1607
|
|
|
1559
|
-
unless records.all?(
|
|
1560
|
-
raise ArgumentError, "You must only pass a single or collection of #{
|
|
1608
|
+
unless records.all?(model) && relations.all? { |relation| relation.model == model }
|
|
1609
|
+
raise ArgumentError, "You must only pass a single or collection of #{model.name} objects to ##{__callee__}."
|
|
1561
1610
|
end
|
|
1562
1611
|
|
|
1563
1612
|
spawn.excluding!(records + relations.flat_map(&:ids))
|
|
@@ -1565,19 +1614,19 @@ module ActiveRecord
|
|
|
1565
1614
|
alias :without :excluding
|
|
1566
1615
|
|
|
1567
1616
|
def excluding!(records) # :nodoc:
|
|
1568
|
-
|
|
1569
|
-
self.where_clause +=
|
|
1617
|
+
ids = records.map { |record| record.is_a?(model) ? record.id : record }
|
|
1618
|
+
self.where_clause += build_where_clause(primary_key => ids).invert
|
|
1570
1619
|
self
|
|
1571
1620
|
end
|
|
1572
1621
|
|
|
1573
1622
|
# Returns the Arel object associated with the relation.
|
|
1574
1623
|
def arel(aliases = nil) # :nodoc:
|
|
1575
|
-
@arel ||=
|
|
1624
|
+
@arel ||= build_arel(aliases)
|
|
1576
1625
|
end
|
|
1577
1626
|
|
|
1578
1627
|
def construct_join_dependency(associations, join_type) # :nodoc:
|
|
1579
1628
|
ActiveRecord::Associations::JoinDependency.new(
|
|
1580
|
-
|
|
1629
|
+
model, table, associations, join_type
|
|
1581
1630
|
)
|
|
1582
1631
|
end
|
|
1583
1632
|
|
|
@@ -1606,15 +1655,15 @@ module ActiveRecord
|
|
|
1606
1655
|
elsif opts.include?("?")
|
|
1607
1656
|
parts = [build_bound_sql_literal(opts, rest)]
|
|
1608
1657
|
else
|
|
1609
|
-
parts = [
|
|
1658
|
+
parts = [Arel.sql(model.sanitize_sql([opts, *rest]))]
|
|
1610
1659
|
end
|
|
1611
1660
|
when Hash
|
|
1612
1661
|
opts = opts.transform_keys do |key|
|
|
1613
1662
|
if key.is_a?(Array)
|
|
1614
|
-
key.map { |k|
|
|
1663
|
+
key.map { |k| model.attribute_aliases[k.to_s] || k.to_s }
|
|
1615
1664
|
else
|
|
1616
1665
|
key = key.to_s
|
|
1617
|
-
|
|
1666
|
+
model.attribute_aliases[key] || key
|
|
1618
1667
|
end
|
|
1619
1668
|
end
|
|
1620
1669
|
references = PredicateBuilder.references(opts)
|
|
@@ -1633,21 +1682,16 @@ module ActiveRecord
|
|
|
1633
1682
|
end
|
|
1634
1683
|
alias :build_having_clause :build_where_clause
|
|
1635
1684
|
|
|
1636
|
-
def async!
|
|
1685
|
+
def async! # :nodoc:
|
|
1637
1686
|
@async = true
|
|
1638
1687
|
self
|
|
1639
1688
|
end
|
|
1640
1689
|
|
|
1641
|
-
|
|
1642
|
-
def arel_columns(columns)
|
|
1690
|
+
def arel_columns(columns) # :nodoc:
|
|
1643
1691
|
columns.flat_map do |field|
|
|
1644
1692
|
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)
|
|
1693
|
+
when Symbol, String
|
|
1694
|
+
arel_column(field)
|
|
1651
1695
|
when Proc
|
|
1652
1696
|
field.call
|
|
1653
1697
|
when Hash
|
|
@@ -1731,32 +1775,27 @@ module ActiveRecord
|
|
|
1731
1775
|
raise UnmodifiableRelation if @loaded || @arel
|
|
1732
1776
|
end
|
|
1733
1777
|
|
|
1734
|
-
def build_arel(
|
|
1778
|
+
def build_arel(aliases)
|
|
1735
1779
|
arel = Arel::SelectManager.new(table)
|
|
1736
1780
|
|
|
1737
1781
|
build_joins(arel.join_sources, aliases)
|
|
1738
1782
|
|
|
1739
1783
|
arel.where(where_clause.ast) unless where_clause.empty?
|
|
1740
1784
|
arel.having(having_clause.ast) unless having_clause.empty?
|
|
1741
|
-
arel.take(build_cast_value("LIMIT",
|
|
1785
|
+
arel.take(build_cast_value("LIMIT", limit_value)) if limit_value
|
|
1742
1786
|
arel.skip(build_cast_value("OFFSET", offset_value.to_i)) if offset_value
|
|
1743
|
-
arel.group(*arel_columns(group_values
|
|
1787
|
+
arel.group(*arel_columns(group_values)) unless group_values.empty?
|
|
1744
1788
|
|
|
1745
1789
|
build_order(arel)
|
|
1746
1790
|
build_with(arel)
|
|
1747
1791
|
build_select(arel)
|
|
1748
1792
|
|
|
1749
1793
|
arel.optimizer_hints(*optimizer_hints_values) unless optimizer_hints_values.empty?
|
|
1794
|
+
arel.comment(*annotate_values) unless annotate_values.empty?
|
|
1750
1795
|
arel.distinct(distinct_value)
|
|
1751
1796
|
arel.from(build_from) unless from_clause.empty?
|
|
1752
1797
|
arel.lock(lock_value) if lock_value
|
|
1753
1798
|
|
|
1754
|
-
unless annotate_values.empty?
|
|
1755
|
-
annotates = annotate_values
|
|
1756
|
-
annotates = annotates.uniq if annotates.size > 1
|
|
1757
|
-
arel.comment(*annotates)
|
|
1758
|
-
end
|
|
1759
|
-
|
|
1760
1799
|
arel
|
|
1761
1800
|
end
|
|
1762
1801
|
|
|
@@ -1830,7 +1869,7 @@ module ActiveRecord
|
|
|
1830
1869
|
|
|
1831
1870
|
joins = joins_values.dup
|
|
1832
1871
|
if joins.last.is_a?(ActiveRecord::Associations::JoinDependency)
|
|
1833
|
-
stashed_eager_load = joins.pop if joins.last.base_klass ==
|
|
1872
|
+
stashed_eager_load = joins.pop if joins.last.base_klass == model
|
|
1834
1873
|
end
|
|
1835
1874
|
|
|
1836
1875
|
joins.each_with_index do |join, i|
|
|
@@ -1887,8 +1926,8 @@ module ActiveRecord
|
|
|
1887
1926
|
def build_select(arel)
|
|
1888
1927
|
if select_values.any?
|
|
1889
1928
|
arel.project(*arel_columns(select_values))
|
|
1890
|
-
elsif
|
|
1891
|
-
arel.project(*
|
|
1929
|
+
elsif model.ignored_columns.any? || model.enumerate_columns_in_select_statements || model.only_columns.any?
|
|
1930
|
+
arel.project(*model.column_names.map { |field| table[field] })
|
|
1892
1931
|
else
|
|
1893
1932
|
arel.project(table[Arel.star])
|
|
1894
1933
|
end
|
|
@@ -1912,7 +1951,8 @@ module ActiveRecord
|
|
|
1912
1951
|
|
|
1913
1952
|
def build_with_expression_from_value(value, nested = false)
|
|
1914
1953
|
case value
|
|
1915
|
-
when Arel::Nodes::SqlLiteral
|
|
1954
|
+
when Arel::Nodes::SqlLiteral, Arel::Nodes::BoundSqlLiteral
|
|
1955
|
+
Arel::Nodes::Grouping.new(value)
|
|
1916
1956
|
when ActiveRecord::Relation
|
|
1917
1957
|
if nested
|
|
1918
1958
|
value.arel.ast
|
|
@@ -1939,37 +1979,76 @@ module ActiveRecord
|
|
|
1939
1979
|
with_table = Arel::Table.new(name)
|
|
1940
1980
|
|
|
1941
1981
|
table.join(with_table, kind).on(
|
|
1942
|
-
with_table[
|
|
1982
|
+
with_table[model.model_name.to_s.foreign_key].eq(table[model.primary_key])
|
|
1943
1983
|
).join_sources.first
|
|
1944
1984
|
end
|
|
1945
1985
|
|
|
1986
|
+
def arel_columns_from_hash(fields)
|
|
1987
|
+
fields.flat_map do |table_name, columns|
|
|
1988
|
+
table_name = table_name.name if table_name.is_a?(Symbol)
|
|
1989
|
+
case columns
|
|
1990
|
+
when Symbol, String
|
|
1991
|
+
arel_column_with_table(table_name, columns)
|
|
1992
|
+
when Array
|
|
1993
|
+
columns.map do |column|
|
|
1994
|
+
arel_column_with_table(table_name, column)
|
|
1995
|
+
end
|
|
1996
|
+
else
|
|
1997
|
+
raise TypeError, "Expected Symbol, String or Array, got: #{columns.class}"
|
|
1998
|
+
end
|
|
1999
|
+
end
|
|
2000
|
+
end
|
|
2001
|
+
|
|
2002
|
+
def arel_column_with_table(table_name, column_name)
|
|
2003
|
+
self.references_values |= [Arel.sql(table_name, retryable: true)]
|
|
2004
|
+
|
|
2005
|
+
if column_name.is_a?(Symbol) || !column_name.match?(/\W/)
|
|
2006
|
+
predicate_builder.resolve_arel_attribute(table_name, column_name) do
|
|
2007
|
+
lookup_table_klass_from_join_dependencies(table_name)
|
|
2008
|
+
end
|
|
2009
|
+
else
|
|
2010
|
+
Arel.sql("#{model.adapter_class.quote_table_name(table_name)}.#{column_name}")
|
|
2011
|
+
end
|
|
2012
|
+
end
|
|
2013
|
+
|
|
1946
2014
|
def arel_column(field)
|
|
1947
|
-
field =
|
|
2015
|
+
field = field.name if is_symbol = field.is_a?(Symbol)
|
|
2016
|
+
|
|
2017
|
+
field = model.attribute_aliases[field] || field
|
|
1948
2018
|
from = from_clause.name || from_clause.value
|
|
1949
2019
|
|
|
1950
|
-
if
|
|
2020
|
+
if model.columns_hash.key?(field) && (!from || table_name_matches?(from))
|
|
1951
2021
|
table[field]
|
|
1952
2022
|
elsif /\A(?<table>(?:\w+\.)?\w+)\.(?<column>\w+)\z/ =~ field
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
lookup_table_klass_from_join_dependencies(table)
|
|
1956
|
-
end
|
|
1957
|
-
else
|
|
2023
|
+
arel_column_with_table(table, column)
|
|
2024
|
+
elsif block_given?
|
|
1958
2025
|
yield field
|
|
2026
|
+
elsif Arel.arel_node?(field)
|
|
2027
|
+
field
|
|
2028
|
+
elsif is_symbol
|
|
2029
|
+
Arel.sql(model.adapter_class.quote_table_name(field), retryable: true)
|
|
2030
|
+
else
|
|
2031
|
+
Arel.sql(field)
|
|
1959
2032
|
end
|
|
1960
2033
|
end
|
|
1961
2034
|
|
|
1962
2035
|
def table_name_matches?(from)
|
|
1963
2036
|
table_name = Regexp.escape(table.name)
|
|
1964
|
-
quoted_table_name = Regexp.escape(adapter_class.quote_table_name(table.name))
|
|
2037
|
+
quoted_table_name = Regexp.escape(model.adapter_class.quote_table_name(table.name))
|
|
1965
2038
|
/(?:\A|(?<!FROM)\s)(?:\b#{table_name}\b|#{quoted_table_name})(?!\.)/i.match?(from.to_s)
|
|
1966
2039
|
end
|
|
1967
2040
|
|
|
1968
2041
|
def reverse_sql_order(order_query)
|
|
1969
2042
|
if order_query.empty?
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
2043
|
+
if !_reverse_order_columns.empty?
|
|
2044
|
+
return _reverse_order_columns.map { |column| table[column].desc }
|
|
2045
|
+
end
|
|
2046
|
+
|
|
2047
|
+
raise IrreversibleOrderError, <<~MSG.squish
|
|
2048
|
+
Relation has no order values, and #{model} has no order columns to use as a default.
|
|
2049
|
+
Set at least one of `implicit_order_column`, or `primary_key` on the model when no
|
|
2050
|
+
`order `is specified on the relation.
|
|
2051
|
+
MSG
|
|
1973
2052
|
end
|
|
1974
2053
|
|
|
1975
2054
|
order_query.flat_map do |o|
|
|
@@ -1994,6 +2073,13 @@ module ActiveRecord
|
|
|
1994
2073
|
end
|
|
1995
2074
|
end
|
|
1996
2075
|
|
|
2076
|
+
def _reverse_order_columns
|
|
2077
|
+
roc = []
|
|
2078
|
+
roc << model.implicit_order_column if model.implicit_order_column
|
|
2079
|
+
roc << model.primary_key if model.primary_key
|
|
2080
|
+
roc.flatten.uniq.compact
|
|
2081
|
+
end
|
|
2082
|
+
|
|
1997
2083
|
def does_not_support_reverse?(order)
|
|
1998
2084
|
# Account for String subclasses like Arel::Nodes::SqlLiteral that
|
|
1999
2085
|
# override methods like #count.
|
|
@@ -2032,7 +2118,7 @@ module ActiveRecord
|
|
|
2032
2118
|
end
|
|
2033
2119
|
|
|
2034
2120
|
def preprocess_order_args(order_args)
|
|
2035
|
-
|
|
2121
|
+
model.disallow_raw_sql!(
|
|
2036
2122
|
flattened_args(order_args),
|
|
2037
2123
|
permit: model.adapter_class.column_name_with_order_matcher
|
|
2038
2124
|
)
|
|
@@ -2070,7 +2156,7 @@ module ActiveRecord
|
|
|
2070
2156
|
|
|
2071
2157
|
def sanitize_order_arguments(order_args)
|
|
2072
2158
|
order_args.map! do |arg|
|
|
2073
|
-
|
|
2159
|
+
model.sanitize_sql_for_order(arg)
|
|
2074
2160
|
end
|
|
2075
2161
|
end
|
|
2076
2162
|
|
|
@@ -2108,17 +2194,18 @@ module ActiveRecord
|
|
|
2108
2194
|
if attr_name == "count" && !group_values.empty?
|
|
2109
2195
|
table[attr_name]
|
|
2110
2196
|
else
|
|
2111
|
-
Arel.sql(adapter_class.quote_table_name(attr_name), retryable: true)
|
|
2197
|
+
Arel.sql(model.adapter_class.quote_table_name(attr_name), retryable: true)
|
|
2112
2198
|
end
|
|
2113
2199
|
end
|
|
2114
2200
|
end
|
|
2115
2201
|
|
|
2116
|
-
def build_case_for_value_position(column, values)
|
|
2202
|
+
def build_case_for_value_position(column, values, filter: true)
|
|
2117
2203
|
node = Arel::Nodes::Case.new
|
|
2118
2204
|
values.each.with_index(1) do |value, order|
|
|
2119
2205
|
node.when(column.eq(value)).then(order)
|
|
2120
2206
|
end
|
|
2121
2207
|
|
|
2208
|
+
node = node.else(values.length + 1) unless filter
|
|
2122
2209
|
Arel::Nodes::Ascending.new(node)
|
|
2123
2210
|
end
|
|
2124
2211
|
|
|
@@ -2146,6 +2233,10 @@ module ActiveRecord
|
|
|
2146
2233
|
end
|
|
2147
2234
|
end
|
|
2148
2235
|
|
|
2236
|
+
def qualify_attribute_with_table_name(attr)
|
|
2237
|
+
attr.to_s.include?(".") ? attr : predicate_builder.resolve_arel_attribute(table_name, attr)
|
|
2238
|
+
end
|
|
2239
|
+
|
|
2149
2240
|
# Checks to make sure that the arguments are not blank. Note that if some
|
|
2150
2241
|
# blank-like object were initially passed into the query method, then this
|
|
2151
2242
|
# method will not raise an error.
|
|
@@ -2176,34 +2267,47 @@ module ActiveRecord
|
|
|
2176
2267
|
def process_select_args(fields)
|
|
2177
2268
|
fields.flat_map do |field|
|
|
2178
2269
|
if field.is_a?(Hash)
|
|
2179
|
-
|
|
2270
|
+
arel_column_aliases_from_hash(field)
|
|
2180
2271
|
else
|
|
2181
2272
|
field
|
|
2182
2273
|
end
|
|
2183
2274
|
end
|
|
2184
2275
|
end
|
|
2185
2276
|
|
|
2186
|
-
def
|
|
2277
|
+
def cast_values_for_in_order_of(values, type_caster)
|
|
2278
|
+
bad_value = Symbol # use some object that can not be a valid value
|
|
2279
|
+
|
|
2280
|
+
values = values.map do |value|
|
|
2281
|
+
serialized = type_caster.serialize(value) if type_caster.serializable?(value)
|
|
2282
|
+
|
|
2283
|
+
if value.nil?
|
|
2284
|
+
nil
|
|
2285
|
+
elsif !serialized.nil?
|
|
2286
|
+
serialized
|
|
2287
|
+
else
|
|
2288
|
+
bad_value
|
|
2289
|
+
end
|
|
2290
|
+
end
|
|
2291
|
+
|
|
2292
|
+
values.without(bad_value)
|
|
2293
|
+
end
|
|
2294
|
+
|
|
2295
|
+
def arel_column_aliases_from_hash(fields)
|
|
2187
2296
|
fields.flat_map do |key, columns_aliases|
|
|
2297
|
+
table_name = key.is_a?(Symbol) ? key.name : key
|
|
2188
2298
|
case columns_aliases
|
|
2189
2299
|
when Hash
|
|
2190
2300
|
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)
|
|
2301
|
+
arel_column_with_table(table_name, column)
|
|
2302
|
+
.as(model.adapter_class.quote_column_name(column_alias.to_s))
|
|
2198
2303
|
end
|
|
2199
2304
|
when Array
|
|
2200
2305
|
columns_aliases.map do |column|
|
|
2201
|
-
|
|
2306
|
+
arel_column_with_table(table_name, column)
|
|
2202
2307
|
end
|
|
2203
2308
|
when String, Symbol
|
|
2204
|
-
arel_column(key
|
|
2205
|
-
|
|
2206
|
-
end.as(columns_aliases.to_s)
|
|
2309
|
+
arel_column(key)
|
|
2310
|
+
.as(model.adapter_class.quote_column_name(columns_aliases.to_s))
|
|
2207
2311
|
end
|
|
2208
2312
|
end
|
|
2209
2313
|
end
|
|
@@ -2224,11 +2328,11 @@ module ActiveRecord
|
|
|
2224
2328
|
values = other.values
|
|
2225
2329
|
STRUCTURAL_VALUE_METHODS.reject do |method|
|
|
2226
2330
|
v1, v2 = @values[method], values[method]
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2331
|
+
|
|
2332
|
+
# `and`/`or` are focused to combine where-like clauses, so it relaxes
|
|
2333
|
+
# the difference when other's multi values are uninitialized.
|
|
2334
|
+
next true if v1.is_a?(Array) && v2.nil?
|
|
2335
|
+
|
|
2232
2336
|
v1 == v2
|
|
2233
2337
|
end
|
|
2234
2338
|
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)
|
|
@@ -194,7 +194,7 @@ module ActiveRecord
|
|
|
194
194
|
non_empty_predicates.map do |node|
|
|
195
195
|
case node
|
|
196
196
|
when Arel::Nodes::SqlLiteral, ::String
|
|
197
|
-
|
|
197
|
+
Arel::Nodes::Grouping.new(node)
|
|
198
198
|
else node
|
|
199
199
|
end
|
|
200
200
|
end
|
|
@@ -205,13 +205,6 @@ module ActiveRecord
|
|
|
205
205
|
predicates - ARRAY_WITH_EMPTY_STRING
|
|
206
206
|
end
|
|
207
207
|
|
|
208
|
-
def wrap_sql_literal(node)
|
|
209
|
-
if ::String === node
|
|
210
|
-
node = Arel.sql(node)
|
|
211
|
-
end
|
|
212
|
-
Arel::Nodes::Grouping.new(node)
|
|
213
|
-
end
|
|
214
|
-
|
|
215
208
|
def extract_node_value(node)
|
|
216
209
|
if node.respond_to?(:value_before_type_cast)
|
|
217
210
|
node.value_before_type_cast
|