activerecord 5.0.7 → 5.1.7
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 +5 -5
- data/CHANGELOG.md +657 -2080
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/examples/performance.rb +28 -28
- data/examples/simple.rb +3 -3
- data/lib/active_record/aggregations.rb +244 -244
- data/lib/active_record/association_relation.rb +5 -5
- data/lib/active_record/associations/alias_tracker.rb +10 -11
- data/lib/active_record/associations/association.rb +23 -5
- data/lib/active_record/associations/association_scope.rb +95 -81
- data/lib/active_record/associations/belongs_to_association.rb +7 -4
- data/lib/active_record/associations/builder/belongs_to.rb +30 -16
- data/lib/active_record/associations/builder/collection_association.rb +1 -2
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +27 -27
- data/lib/active_record/associations/collection_association.rb +36 -205
- data/lib/active_record/associations/collection_proxy.rb +132 -63
- data/lib/active_record/associations/has_many_association.rb +10 -19
- data/lib/active_record/associations/has_many_through_association.rb +12 -4
- data/lib/active_record/associations/has_one_association.rb +24 -28
- data/lib/active_record/associations/has_one_through_association.rb +5 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +4 -28
- data/lib/active_record/associations/join_dependency/join_base.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
- data/lib/active_record/associations/join_dependency.rb +121 -118
- data/lib/active_record/associations/preloader/association.rb +64 -64
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -2
- data/lib/active_record/associations/preloader/collection_association.rb +6 -6
- data/lib/active_record/associations/preloader/has_many.rb +0 -2
- data/lib/active_record/associations/preloader/singular_association.rb +6 -8
- data/lib/active_record/associations/preloader/through_association.rb +41 -41
- data/lib/active_record/associations/preloader.rb +94 -94
- data/lib/active_record/associations/singular_association.rb +8 -25
- data/lib/active_record/associations/through_association.rb +2 -5
- data/lib/active_record/associations.rb +1591 -1562
- data/lib/active_record/attribute/user_provided_default.rb +4 -2
- data/lib/active_record/attribute.rb +98 -71
- data/lib/active_record/attribute_assignment.rb +61 -61
- data/lib/active_record/attribute_decorators.rb +35 -13
- data/lib/active_record/attribute_methods/before_type_cast.rb +7 -7
- data/lib/active_record/attribute_methods/dirty.rb +229 -46
- data/lib/active_record/attribute_methods/primary_key.rb +74 -73
- data/lib/active_record/attribute_methods/read.rb +39 -35
- data/lib/active_record/attribute_methods/serialization.rb +7 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +35 -58
- data/lib/active_record/attribute_methods/write.rb +30 -33
- data/lib/active_record/attribute_methods.rb +56 -65
- data/lib/active_record/attribute_mutation_tracker.rb +63 -11
- data/lib/active_record/attribute_set/builder.rb +27 -33
- data/lib/active_record/attribute_set/yaml_encoder.rb +41 -0
- data/lib/active_record/attribute_set.rb +9 -6
- data/lib/active_record/attributes.rb +22 -22
- data/lib/active_record/autosave_association.rb +18 -13
- data/lib/active_record/base.rb +24 -22
- data/lib/active_record/callbacks.rb +56 -14
- data/lib/active_record/coders/yaml_column.rb +9 -11
- data/lib/active_record/collection_cache_key.rb +3 -4
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +330 -284
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +1 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +39 -37
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +32 -27
- data/lib/active_record/connection_adapters/abstract/quoting.rb +62 -51
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +10 -20
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +74 -79
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +53 -41
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +120 -100
- data/lib/active_record/connection_adapters/abstract/transaction.rb +49 -43
- data/lib/active_record/connection_adapters/abstract_adapter.rb +165 -135
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +404 -424
- data/lib/active_record/connection_adapters/column.rb +26 -4
- data/lib/active_record/connection_adapters/connection_specification.rb +128 -118
- data/lib/active_record/connection_adapters/mysql/column.rb +6 -31
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +36 -49
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +22 -22
- data/lib/active_record/connection_adapters/mysql/quoting.rb +6 -12
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +49 -45
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +16 -19
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -28
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +43 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +7 -6
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +23 -27
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +32 -53
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +16 -16
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +0 -10
- data/lib/active_record/connection_adapters/postgresql/oid/{rails_5_1_point.rb → legacy_point.rb} +9 -16
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +28 -8
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +32 -30
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +51 -51
- data/lib/active_record/connection_adapters/postgresql/oid.rb +22 -21
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +40 -35
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +37 -24
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +19 -23
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +182 -222
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +6 -4
- data/lib/active_record/connection_adapters/postgresql/utils.rb +7 -5
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +198 -167
- data/lib/active_record/connection_adapters/schema_cache.rb +16 -7
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +3 -3
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +16 -19
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +1 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +28 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +17 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +32 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +184 -167
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -7
- data/lib/active_record/connection_handling.rb +14 -26
- data/lib/active_record/core.rb +109 -93
- data/lib/active_record/counter_cache.rb +60 -13
- data/lib/active_record/define_callbacks.rb +20 -0
- data/lib/active_record/dynamic_matchers.rb +80 -79
- data/lib/active_record/enum.rb +8 -6
- data/lib/active_record/errors.rb +64 -15
- data/lib/active_record/explain.rb +1 -2
- data/lib/active_record/explain_registry.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +7 -4
- data/lib/active_record/fixture_set/file.rb +11 -8
- data/lib/active_record/fixtures.rb +66 -53
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/inheritance.rb +93 -79
- data/lib/active_record/integration.rb +7 -7
- data/lib/active_record/internal_metadata.rb +3 -16
- data/lib/active_record/legacy_yaml_adapter.rb +1 -1
- data/lib/active_record/locking/optimistic.rb +69 -74
- data/lib/active_record/locking/pessimistic.rb +10 -1
- data/lib/active_record/log_subscriber.rb +23 -28
- data/lib/active_record/migration/command_recorder.rb +94 -94
- data/lib/active_record/migration/compatibility.rb +100 -47
- data/lib/active_record/migration/join_table.rb +6 -6
- data/lib/active_record/migration.rb +153 -155
- data/lib/active_record/model_schema.rb +94 -107
- data/lib/active_record/nested_attributes.rb +200 -199
- data/lib/active_record/null_relation.rb +11 -34
- data/lib/active_record/persistence.rb +65 -50
- data/lib/active_record/query_cache.rb +2 -6
- data/lib/active_record/querying.rb +3 -4
- data/lib/active_record/railtie.rb +16 -17
- data/lib/active_record/railties/controller_runtime.rb +6 -2
- data/lib/active_record/railties/databases.rake +105 -133
- data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
- data/lib/active_record/readonly_attributes.rb +2 -2
- data/lib/active_record/reflection.rb +154 -108
- data/lib/active_record/relation/batches/batch_enumerator.rb +1 -1
- data/lib/active_record/relation/batches.rb +80 -51
- data/lib/active_record/relation/calculations.rb +169 -162
- data/lib/active_record/relation/delegation.rb +32 -31
- data/lib/active_record/relation/finder_methods.rb +197 -231
- data/lib/active_record/relation/merger.rb +58 -62
- data/lib/active_record/relation/predicate_builder/array_handler.rb +7 -5
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +23 -23
- data/lib/active_record/relation/predicate_builder/base_handler.rb +3 -1
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +0 -8
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +12 -10
- data/lib/active_record/relation/predicate_builder/range_handler.rb +0 -8
- data/lib/active_record/relation/predicate_builder.rb +92 -89
- data/lib/active_record/relation/query_attribute.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +255 -293
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +4 -5
- data/lib/active_record/relation/where_clause.rb +80 -65
- data/lib/active_record/relation/where_clause_factory.rb +47 -8
- data/lib/active_record/relation.rb +93 -119
- data/lib/active_record/result.rb +41 -32
- data/lib/active_record/runtime_registry.rb +3 -3
- data/lib/active_record/sanitization.rb +176 -192
- data/lib/active_record/schema.rb +3 -3
- data/lib/active_record/schema_dumper.rb +15 -38
- data/lib/active_record/schema_migration.rb +8 -4
- data/lib/active_record/scoping/default.rb +90 -90
- data/lib/active_record/scoping/named.rb +11 -11
- data/lib/active_record/scoping.rb +6 -6
- data/lib/active_record/secure_token.rb +2 -2
- data/lib/active_record/statement_cache.rb +13 -15
- data/lib/active_record/store.rb +31 -32
- data/lib/active_record/suppressor.rb +2 -1
- data/lib/active_record/table_metadata.rb +9 -5
- data/lib/active_record/tasks/database_tasks.rb +65 -55
- data/lib/active_record/tasks/mysql_database_tasks.rb +76 -73
- data/lib/active_record/tasks/postgresql_database_tasks.rb +72 -47
- data/lib/active_record/tasks/sqlite_database_tasks.rb +18 -16
- data/lib/active_record/timestamp.rb +46 -25
- data/lib/active_record/touch_later.rb +1 -2
- data/lib/active_record/transactions.rb +97 -109
- data/lib/active_record/type/adapter_specific_registry.rb +46 -42
- data/lib/active_record/type/decimal_without_scale.rb +13 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +3 -3
- data/lib/active_record/type/internal/abstract_json.rb +4 -0
- data/lib/active_record/type/serialized.rb +14 -8
- data/lib/active_record/type/text.rb +9 -0
- data/lib/active_record/type/time.rb +0 -1
- data/lib/active_record/type/type_map.rb +11 -15
- data/lib/active_record/type/unsigned_integer.rb +15 -0
- data/lib/active_record/type.rb +17 -13
- data/lib/active_record/type_caster/connection.rb +8 -6
- data/lib/active_record/type_caster/map.rb +3 -1
- data/lib/active_record/type_caster.rb +2 -2
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record/validations/presence.rb +2 -2
- data/lib/active_record/validations/uniqueness.rb +8 -39
- data/lib/active_record/validations.rb +4 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +20 -20
- data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -34
- data/lib/rails/generators/active_record/migration.rb +1 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +9 -9
- data/lib/rails/generators/active_record.rb +4 -4
- metadata +24 -13
- data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "active_support/core_ext/hash/keys"
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
class Relation
|
@@ -83,85 +83,81 @@ module ActiveRecord
|
|
83
83
|
|
84
84
|
private
|
85
85
|
|
86
|
-
|
87
|
-
|
86
|
+
def merge_preloads
|
87
|
+
return if other.preload_values.empty? && other.includes_values.empty?
|
88
88
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
89
|
+
if other.klass == relation.klass
|
90
|
+
relation.preload!(*other.preload_values) unless other.preload_values.empty?
|
91
|
+
relation.includes!(other.includes_values) unless other.includes_values.empty?
|
92
|
+
else
|
93
|
+
reflection = relation.klass.reflect_on_all_associations.find do |r|
|
94
|
+
r.class_name == other.klass.name
|
95
|
+
end || return
|
96
96
|
|
97
|
-
|
98
|
-
|
99
|
-
|
97
|
+
unless other.preload_values.empty?
|
98
|
+
relation.preload! reflection.name => other.preload_values
|
99
|
+
end
|
100
100
|
|
101
|
-
|
102
|
-
|
101
|
+
unless other.includes_values.empty?
|
102
|
+
relation.includes! reflection.name => other.includes_values
|
103
|
+
end
|
103
104
|
end
|
104
105
|
end
|
105
|
-
end
|
106
106
|
|
107
|
-
|
108
|
-
|
107
|
+
def merge_joins
|
108
|
+
return if other.joins_values.blank?
|
109
109
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
110
|
+
if other.klass == relation.klass
|
111
|
+
relation.joins!(*other.joins_values)
|
112
|
+
else
|
113
|
+
joins_dependency, rest = other.joins_values.partition do |join|
|
114
|
+
case join
|
115
|
+
when Hash, Symbol, Array
|
116
|
+
true
|
117
|
+
else
|
118
|
+
false
|
119
|
+
end
|
119
120
|
end
|
120
|
-
end
|
121
|
-
|
122
|
-
join_dependency = ActiveRecord::Associations::JoinDependency.new(other.klass,
|
123
|
-
joins_dependency,
|
124
|
-
[])
|
125
|
-
relation.joins! rest
|
126
121
|
|
127
|
-
|
128
|
-
|
129
|
-
|
122
|
+
join_dependency = ActiveRecord::Associations::JoinDependency.new(other.klass,
|
123
|
+
joins_dependency,
|
124
|
+
[])
|
125
|
+
relation.joins! rest
|
130
126
|
|
131
|
-
|
132
|
-
|
133
|
-
# override any order specified in the original relation
|
134
|
-
relation.reorder! other.order_values
|
135
|
-
elsif other.order_values
|
136
|
-
# merge in order_values from relation
|
137
|
-
relation.order! other.order_values
|
127
|
+
@relation = relation.joins join_dependency
|
128
|
+
end
|
138
129
|
end
|
139
130
|
|
140
|
-
|
141
|
-
|
131
|
+
def merge_multi_values
|
132
|
+
if other.reordering_value
|
133
|
+
# override any order specified in the original relation
|
134
|
+
relation.reorder! other.order_values
|
135
|
+
elsif other.order_values
|
136
|
+
# merge in order_values from relation
|
137
|
+
relation.order! other.order_values
|
138
|
+
end
|
142
139
|
|
143
|
-
|
144
|
-
if relation.from_clause.empty?
|
145
|
-
relation.from_clause = other.from_clause
|
140
|
+
relation.extend(*other.extending_values) unless other.extending_values.blank?
|
146
141
|
end
|
147
|
-
relation.lock_value ||= other.lock_value
|
148
142
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
143
|
+
def merge_single_values
|
144
|
+
if relation.from_clause.empty?
|
145
|
+
relation.from_clause = other.from_clause
|
146
|
+
end
|
147
|
+
relation.lock_value ||= other.lock_value
|
153
148
|
|
154
|
-
|
155
|
-
|
156
|
-
|
149
|
+
unless other.create_with_value.blank?
|
150
|
+
relation.create_with_value = (relation.create_with_value || {}).merge(other.create_with_value)
|
151
|
+
end
|
152
|
+
end
|
157
153
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
154
|
+
def merge_clauses
|
155
|
+
CLAUSE_METHODS.each do |method|
|
156
|
+
clause = relation.get_value(method)
|
157
|
+
other_clause = other.get_value(method)
|
158
|
+
relation.set_value(method, clause.merge(other_clause))
|
159
|
+
end
|
163
160
|
end
|
164
|
-
end
|
165
161
|
end
|
166
162
|
end
|
167
163
|
end
|
@@ -29,15 +29,17 @@ module ActiveRecord
|
|
29
29
|
array_predicates.inject { |composite, predicate| composite.or(predicate) }
|
30
30
|
end
|
31
31
|
|
32
|
+
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
33
|
+
# Workaround for Ruby 2.2 "private attribute?" warning.
|
32
34
|
protected
|
33
35
|
|
34
|
-
|
36
|
+
attr_reader :predicate_builder
|
35
37
|
|
36
|
-
|
37
|
-
|
38
|
-
|
38
|
+
module NullPredicate # :nodoc:
|
39
|
+
def self.or(other)
|
40
|
+
other
|
41
|
+
end
|
39
42
|
end
|
40
|
-
end
|
41
43
|
end
|
42
44
|
end
|
43
45
|
end
|
@@ -2,13 +2,14 @@ module ActiveRecord
|
|
2
2
|
class PredicateBuilder
|
3
3
|
class AssociationQueryHandler # :nodoc:
|
4
4
|
def self.value_for(table, column, value)
|
5
|
-
|
5
|
+
associated_table = table.associated_table(column)
|
6
|
+
klass = if associated_table.polymorphic_association? && ::Array === value && value.first.is_a?(Base)
|
6
7
|
PolymorphicArrayValue
|
7
8
|
else
|
8
9
|
AssociationQueryValue
|
9
10
|
end
|
10
11
|
|
11
|
-
klass.new(
|
12
|
+
klass.new(associated_table, value)
|
12
13
|
end
|
13
14
|
|
14
15
|
def initialize(predicate_builder)
|
@@ -27,9 +28,11 @@ module ActiveRecord
|
|
27
28
|
predicate_builder.build_from_hash(queries)
|
28
29
|
end
|
29
30
|
|
31
|
+
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
32
|
+
# Workaround for Ruby 2.2 "private attribute?" warning.
|
30
33
|
protected
|
31
34
|
|
32
|
-
|
35
|
+
attr_reader :predicate_builder
|
33
36
|
end
|
34
37
|
|
35
38
|
class AssociationQueryValue # :nodoc:
|
@@ -59,30 +62,27 @@ module ActiveRecord
|
|
59
62
|
|
60
63
|
private
|
61
64
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
+
def primary_key
|
66
|
+
associated_table.association_primary_key(base_class)
|
67
|
+
end
|
65
68
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
when Base
|
74
|
-
value.class.base_class
|
69
|
+
def polymorphic_base_class_from_value
|
70
|
+
case value
|
71
|
+
when Relation
|
72
|
+
value.klass.base_class
|
73
|
+
when Base
|
74
|
+
value.class.base_class
|
75
|
+
end
|
75
76
|
end
|
76
|
-
end
|
77
77
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
78
|
+
def convert_to_id(value)
|
79
|
+
case value
|
80
|
+
when Base
|
81
|
+
value._read_attribute(primary_key)
|
82
|
+
else
|
83
|
+
value
|
84
|
+
end
|
84
85
|
end
|
85
|
-
end
|
86
86
|
end
|
87
87
|
end
|
88
88
|
end
|
@@ -9,9 +9,11 @@ module ActiveRecord
|
|
9
9
|
predicate_builder.build(attribute, value.id)
|
10
10
|
end
|
11
11
|
|
12
|
+
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
13
|
+
# Workaround for Ruby 2.2 "private attribute?" warning.
|
12
14
|
protected
|
13
15
|
|
14
|
-
|
16
|
+
attr_reader :predicate_builder
|
15
17
|
end
|
16
18
|
end
|
17
19
|
end
|
@@ -1,17 +1,9 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
class PredicateBuilder
|
3
3
|
class BasicObjectHandler # :nodoc:
|
4
|
-
def initialize(predicate_builder)
|
5
|
-
@predicate_builder = predicate_builder
|
6
|
-
end
|
7
|
-
|
8
4
|
def call(attribute, value)
|
9
5
|
attribute.eq(value)
|
10
6
|
end
|
11
|
-
|
12
|
-
protected
|
13
|
-
|
14
|
-
attr_reader :predicate_builder
|
15
7
|
end
|
16
8
|
end
|
17
9
|
end
|
@@ -21,9 +21,11 @@ module ActiveRecord
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
+
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
25
|
+
# Workaround for Ruby 2.2 "private attribute?" warning.
|
24
26
|
protected
|
25
27
|
|
26
|
-
|
28
|
+
attr_reader :predicate_builder
|
27
29
|
end
|
28
30
|
|
29
31
|
class PolymorphicArrayValue # :nodoc:
|
@@ -41,17 +43,17 @@ module ActiveRecord
|
|
41
43
|
|
42
44
|
private
|
43
45
|
|
44
|
-
|
45
|
-
|
46
|
-
|
46
|
+
def primary_key(value)
|
47
|
+
associated_table.association_primary_key(base_class(value))
|
48
|
+
end
|
47
49
|
|
48
|
-
|
49
|
-
|
50
|
-
|
50
|
+
def base_class(value)
|
51
|
+
value.class.base_class
|
52
|
+
end
|
51
53
|
|
52
|
-
|
53
|
-
|
54
|
-
|
54
|
+
def convert_to_id(value)
|
55
|
+
value._read_attribute(primary_key(value))
|
56
|
+
end
|
55
57
|
end
|
56
58
|
end
|
57
59
|
end
|
@@ -3,10 +3,6 @@ module ActiveRecord
|
|
3
3
|
class RangeHandler # :nodoc:
|
4
4
|
RangeWithBinds = Struct.new(:begin, :end, :exclude_end?)
|
5
5
|
|
6
|
-
def initialize(predicate_builder)
|
7
|
-
@predicate_builder = predicate_builder
|
8
|
-
end
|
9
|
-
|
10
6
|
def call(attribute, value)
|
11
7
|
if value.begin.respond_to?(:infinite?) && value.begin.infinite?
|
12
8
|
if value.end.respond_to?(:infinite?) && value.end.infinite?
|
@@ -24,10 +20,6 @@ module ActiveRecord
|
|
24
20
|
attribute.between(value)
|
25
21
|
end
|
26
22
|
end
|
27
|
-
|
28
|
-
protected
|
29
|
-
|
30
|
-
attr_reader :predicate_builder
|
31
23
|
end
|
32
24
|
end
|
33
25
|
end
|
@@ -1,13 +1,12 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
class PredicateBuilder # :nodoc:
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require 'active_record/relation/predicate_builder/relation_handler'
|
3
|
+
require "active_record/relation/predicate_builder/array_handler"
|
4
|
+
require "active_record/relation/predicate_builder/association_query_handler"
|
5
|
+
require "active_record/relation/predicate_builder/base_handler"
|
6
|
+
require "active_record/relation/predicate_builder/basic_object_handler"
|
7
|
+
require "active_record/relation/predicate_builder/polymorphic_array_handler"
|
8
|
+
require "active_record/relation/predicate_builder/range_handler"
|
9
|
+
require "active_record/relation/predicate_builder/relation_handler"
|
11
10
|
|
12
11
|
delegate :resolve_column_aliases, to: :table
|
13
12
|
|
@@ -15,11 +14,10 @@ module ActiveRecord
|
|
15
14
|
@table = table
|
16
15
|
@handlers = []
|
17
16
|
|
18
|
-
register_handler(BasicObject, BasicObjectHandler.new
|
19
|
-
register_handler(Class, ClassHandler.new(self))
|
17
|
+
register_handler(BasicObject, BasicObjectHandler.new)
|
20
18
|
register_handler(Base, BaseHandler.new(self))
|
21
|
-
register_handler(Range, RangeHandler.new
|
22
|
-
register_handler(RangeHandler::RangeWithBinds, RangeHandler.new
|
19
|
+
register_handler(Range, RangeHandler.new)
|
20
|
+
register_handler(RangeHandler::RangeWithBinds, RangeHandler.new)
|
23
21
|
register_handler(Relation, RelationHandler.new)
|
24
22
|
register_handler(Array, ArrayHandler.new(self))
|
25
23
|
register_handler(AssociationQueryValue, AssociationQueryHandler.new(self))
|
@@ -36,23 +34,13 @@ module ActiveRecord
|
|
36
34
|
create_binds_for_hash(attributes)
|
37
35
|
end
|
38
36
|
|
39
|
-
def expand(column, value)
|
40
|
-
# Find the foreign key when using queries such as:
|
41
|
-
# Post.where(author: author)
|
42
|
-
#
|
43
|
-
# For polymorphic relationships, find the foreign key and type:
|
44
|
-
# PriceEstimate.where(estimate_of: treasure)
|
45
|
-
value = AssociationQueryHandler.value_for(table, column, value) if table.associated_with?(column)
|
46
|
-
build(table.arel_attribute(column), value)
|
47
|
-
end
|
48
|
-
|
49
37
|
def self.references(attributes)
|
50
38
|
attributes.map do |key, value|
|
51
39
|
if value.is_a?(Hash)
|
52
40
|
key
|
53
41
|
else
|
54
42
|
key = key.to_s
|
55
|
-
key.split(
|
43
|
+
key.split(".".freeze).first if key.include?(".".freeze)
|
56
44
|
end
|
57
45
|
end.compact
|
58
46
|
end
|
@@ -76,93 +64,108 @@ module ActiveRecord
|
|
76
64
|
handler_for(value).call(attribute, value)
|
77
65
|
end
|
78
66
|
|
67
|
+
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
68
|
+
# Workaround for Ruby 2.2 "private attribute?" warning.
|
79
69
|
protected
|
80
70
|
|
81
|
-
|
71
|
+
attr_reader :table
|
82
72
|
|
83
|
-
|
84
|
-
|
73
|
+
def expand_from_hash(attributes)
|
74
|
+
return ["1=0"] if attributes.empty?
|
85
75
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
76
|
+
attributes.flat_map do |key, value|
|
77
|
+
if value.is_a?(Hash) && !table.has_column?(key)
|
78
|
+
associated_predicate_builder(key).expand_from_hash(value)
|
79
|
+
else
|
80
|
+
build(table.arel_attribute(key), value)
|
81
|
+
end
|
91
82
|
end
|
92
83
|
end
|
93
|
-
end
|
94
|
-
|
95
|
-
|
96
|
-
def create_binds_for_hash(attributes)
|
97
|
-
result = attributes.dup
|
98
|
-
binds = []
|
99
84
|
|
100
|
-
attributes
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
binds
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
85
|
+
def create_binds_for_hash(attributes)
|
86
|
+
result = attributes.dup
|
87
|
+
binds = []
|
88
|
+
|
89
|
+
attributes.each do |column_name, value|
|
90
|
+
case
|
91
|
+
when value.is_a?(Hash) && !table.has_column?(column_name)
|
92
|
+
attrs, bvs = associated_predicate_builder(column_name).create_binds_for_hash(value)
|
93
|
+
result[column_name] = attrs
|
94
|
+
binds += bvs
|
95
|
+
next
|
96
|
+
when value.is_a?(Relation)
|
97
|
+
binds += value.bound_attributes
|
98
|
+
when value.is_a?(Range) && !table.type(column_name).force_equality?(value)
|
99
|
+
first = value.begin
|
100
|
+
last = value.end
|
101
|
+
unless first.respond_to?(:infinite?) && first.infinite?
|
102
|
+
binds << build_bind_param(column_name, first)
|
103
|
+
first = Arel::Nodes::BindParam.new
|
104
|
+
end
|
105
|
+
unless last.respond_to?(:infinite?) && last.infinite?
|
106
|
+
binds << build_bind_param(column_name, last)
|
107
|
+
last = Arel::Nodes::BindParam.new
|
108
|
+
end
|
109
|
+
|
110
|
+
result[column_name] = RangeHandler::RangeWithBinds.new(first, last, value.exclude_end?)
|
111
|
+
else
|
112
|
+
if can_be_bound?(column_name, value)
|
113
|
+
result[column_name] = Arel::Nodes::BindParam.new
|
114
|
+
binds << build_bind_param(column_name, value)
|
115
|
+
end
|
118
116
|
end
|
119
117
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
118
|
+
# Find the foreign key when using queries such as:
|
119
|
+
# Post.where(author: author)
|
120
|
+
#
|
121
|
+
# For polymorphic relationships, find the foreign key and type:
|
122
|
+
# PriceEstimate.where(estimate_of: treasure)
|
123
|
+
if table.associated_with?(column_name)
|
124
|
+
result[column_name] = AssociationQueryHandler.value_for(table, column_name, value)
|
125
125
|
end
|
126
126
|
end
|
127
|
-
end
|
128
127
|
|
129
|
-
|
130
|
-
|
128
|
+
[result, binds]
|
129
|
+
end
|
131
130
|
|
132
131
|
private
|
133
132
|
|
134
|
-
|
135
|
-
|
136
|
-
end
|
137
|
-
|
138
|
-
def convert_dot_notation_to_hash(attributes)
|
139
|
-
dot_notation = attributes.select do |k, v|
|
140
|
-
k.include?(".".freeze) && !v.is_a?(Hash)
|
133
|
+
def associated_predicate_builder(association_name)
|
134
|
+
self.class.new(table.associated_table(association_name))
|
141
135
|
end
|
142
136
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
137
|
+
def convert_dot_notation_to_hash(attributes)
|
138
|
+
dot_notation = attributes.select do |k, v|
|
139
|
+
k.include?(".".freeze) && !v.is_a?(Hash)
|
140
|
+
end
|
147
141
|
|
148
|
-
|
149
|
-
|
142
|
+
dot_notation.each_key do |key|
|
143
|
+
table_name, column_name = key.split(".".freeze)
|
144
|
+
value = attributes.delete(key)
|
145
|
+
attributes[table_name] ||= {}
|
150
146
|
|
151
|
-
|
152
|
-
|
147
|
+
attributes[table_name] = attributes[table_name].merge(column_name => value)
|
148
|
+
end
|
153
149
|
|
154
|
-
|
155
|
-
|
156
|
-
end
|
150
|
+
attributes
|
151
|
+
end
|
157
152
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
!table.associated_with?(column_name)
|
162
|
-
end
|
153
|
+
def handler_for(object)
|
154
|
+
@handlers.detect { |klass, _| klass === object }.last
|
155
|
+
end
|
163
156
|
|
164
|
-
|
165
|
-
|
166
|
-
|
157
|
+
def can_be_bound?(column_name, value)
|
158
|
+
return if table.associated_with?(column_name)
|
159
|
+
case value
|
160
|
+
when Array, Range
|
161
|
+
table.type(column_name).force_equality?(value)
|
162
|
+
else
|
163
|
+
!value.nil? && handler_for(value).is_a?(BasicObjectHandler)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def build_bind_param(column_name, value)
|
168
|
+
Relation::QueryAttribute.new(column_name.to_s, value, table.type(column_name))
|
169
|
+
end
|
167
170
|
end
|
168
171
|
end
|