activerecord 5.1.7 → 5.2.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +221 -900
- data/README.rdoc +3 -3
- data/examples/performance.rb +2 -0
- data/examples/simple.rb +2 -0
- data/lib/active_record.rb +10 -3
- data/lib/active_record/aggregations.rb +2 -0
- data/lib/active_record/association_relation.rb +2 -0
- data/lib/active_record/associations.rb +13 -42
- data/lib/active_record/associations/alias_tracker.rb +17 -17
- data/lib/active_record/associations/association.rb +11 -22
- data/lib/active_record/associations/association_scope.rb +32 -44
- data/lib/active_record/associations/belongs_to_association.rb +6 -4
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -1
- data/lib/active_record/associations/builder/association.rb +2 -5
- data/lib/active_record/associations/builder/belongs_to.rb +7 -12
- data/lib/active_record/associations/builder/collection_association.rb +1 -1
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -1
- data/lib/active_record/associations/builder/has_many.rb +2 -0
- data/lib/active_record/associations/builder/has_one.rb +2 -0
- data/lib/active_record/associations/builder/singular_association.rb +2 -0
- data/lib/active_record/associations/collection_association.rb +41 -33
- data/lib/active_record/associations/collection_proxy.rb +11 -14
- data/lib/active_record/associations/foreign_association.rb +2 -0
- data/lib/active_record/associations/has_many_association.rb +4 -2
- data/lib/active_record/associations/has_many_through_association.rb +4 -2
- data/lib/active_record/associations/has_one_association.rb +3 -1
- data/lib/active_record/associations/has_one_through_association.rb +3 -1
- data/lib/active_record/associations/join_dependency.rb +22 -40
- data/lib/active_record/associations/join_dependency/join_association.rb +17 -56
- data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
- data/lib/active_record/associations/join_dependency/join_part.rb +2 -9
- data/lib/active_record/associations/preloader.rb +17 -37
- data/lib/active_record/associations/preloader/association.rb +42 -58
- data/lib/active_record/associations/preloader/through_association.rb +71 -79
- data/lib/active_record/associations/singular_association.rb +14 -10
- data/lib/active_record/associations/through_association.rb +3 -1
- data/lib/active_record/attribute_assignment.rb +2 -0
- data/lib/active_record/attribute_decorators.rb +3 -2
- data/lib/active_record/attribute_methods.rb +47 -7
- data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
- data/lib/active_record/attribute_methods/dirty.rb +25 -214
- data/lib/active_record/attribute_methods/primary_key.rb +7 -6
- data/lib/active_record/attribute_methods/query.rb +2 -0
- data/lib/active_record/attribute_methods/read.rb +8 -2
- data/lib/active_record/attribute_methods/serialization.rb +23 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +6 -8
- data/lib/active_record/attribute_methods/write.rb +21 -9
- data/lib/active_record/attributes.rb +7 -6
- data/lib/active_record/autosave_association.rb +5 -11
- data/lib/active_record/base.rb +2 -0
- data/lib/active_record/callbacks.rb +6 -8
- data/lib/active_record/coders/json.rb +2 -0
- data/lib/active_record/coders/yaml_column.rb +2 -0
- data/lib/active_record/collection_cache_key.rb +10 -5
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +110 -35
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +120 -28
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +7 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +14 -33
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +13 -5
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +40 -2
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +103 -63
- data/lib/active_record/connection_adapters/abstract/transaction.rb +45 -9
- data/lib/active_record/connection_adapters/abstract_adapter.rb +62 -90
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +75 -138
- data/lib/active_record/connection_adapters/column.rb +3 -1
- data/lib/active_record/connection_adapters/connection_specification.rb +17 -3
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +3 -1
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +9 -10
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +5 -3
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +7 -6
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +30 -30
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +91 -1
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -2
- data/lib/active_record/connection_adapters/postgresql/column.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -0
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +3 -5
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +10 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +11 -7
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +79 -65
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +47 -82
- data/lib/active_record/connection_adapters/schema_cache.rb +2 -0
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +19 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -15
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +3 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +71 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +34 -89
- data/lib/active_record/connection_adapters/statement_pool.rb +2 -0
- data/lib/active_record/connection_handling.rb +4 -2
- data/lib/active_record/core.rb +27 -57
- data/lib/active_record/counter_cache.rb +15 -12
- data/lib/active_record/define_callbacks.rb +5 -3
- data/lib/active_record/dynamic_matchers.rb +9 -9
- data/lib/active_record/enum.rb +15 -13
- data/lib/active_record/errors.rb +54 -21
- data/lib/active_record/explain.rb +3 -1
- data/lib/active_record/explain_registry.rb +2 -0
- data/lib/active_record/explain_subscriber.rb +2 -0
- data/lib/active_record/fixture_set/file.rb +2 -0
- data/lib/active_record/fixtures.rb +40 -24
- data/lib/active_record/gem_version.rb +5 -3
- data/lib/active_record/inheritance.rb +6 -5
- data/lib/active_record/integration.rb +58 -19
- data/lib/active_record/internal_metadata.rb +2 -0
- data/lib/active_record/legacy_yaml_adapter.rb +3 -1
- data/lib/active_record/locking/optimistic.rb +31 -20
- data/lib/active_record/locking/pessimistic.rb +10 -7
- data/lib/active_record/log_subscriber.rb +2 -0
- data/lib/active_record/migration.rb +47 -21
- data/lib/active_record/migration/command_recorder.rb +11 -9
- data/lib/active_record/migration/compatibility.rb +20 -2
- data/lib/active_record/migration/join_table.rb +2 -0
- data/lib/active_record/model_schema.rb +29 -38
- data/lib/active_record/nested_attributes.rb +18 -6
- data/lib/active_record/no_touching.rb +3 -1
- data/lib/active_record/null_relation.rb +2 -0
- data/lib/active_record/persistence.rb +184 -40
- data/lib/active_record/query_cache.rb +17 -12
- data/lib/active_record/querying.rb +3 -1
- data/lib/active_record/railtie.rb +54 -1
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +2 -0
- data/lib/active_record/railties/databases.rake +41 -28
- data/lib/active_record/readonly_attributes.rb +3 -2
- data/lib/active_record/reflection.rb +100 -182
- data/lib/active_record/relation.rb +61 -193
- data/lib/active_record/relation/batches.rb +20 -5
- data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
- data/lib/active_record/relation/calculations.rb +40 -23
- data/lib/active_record/relation/delegation.rb +10 -27
- data/lib/active_record/relation/finder_methods.rb +53 -49
- data/lib/active_record/relation/from_clause.rb +2 -8
- data/lib/active_record/relation/merger.rb +22 -19
- data/lib/active_record/relation/predicate_builder.rb +42 -79
- data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -7
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +12 -1
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +54 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -6
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
- data/lib/active_record/relation/query_attribute.rb +9 -2
- data/lib/active_record/relation/query_methods.rb +80 -69
- data/lib/active_record/relation/record_fetch_warning.rb +2 -0
- data/lib/active_record/relation/spawn_methods.rb +2 -0
- data/lib/active_record/relation/where_clause.rb +50 -67
- data/lib/active_record/relation/where_clause_factory.rb +4 -46
- data/lib/active_record/result.rb +2 -0
- data/lib/active_record/runtime_registry.rb +2 -0
- data/lib/active_record/sanitization.rb +15 -9
- data/lib/active_record/schema.rb +3 -1
- data/lib/active_record/schema_dumper.rb +24 -23
- data/lib/active_record/schema_migration.rb +2 -0
- data/lib/active_record/scoping.rb +9 -8
- data/lib/active_record/scoping/default.rb +6 -7
- data/lib/active_record/scoping/named.rb +15 -7
- data/lib/active_record/secure_token.rb +2 -0
- data/lib/active_record/serialization.rb +2 -0
- data/lib/active_record/statement_cache.rb +22 -12
- data/lib/active_record/store.rb +2 -0
- data/lib/active_record/suppressor.rb +2 -0
- data/lib/active_record/table_metadata.rb +3 -1
- data/lib/active_record/tasks/database_tasks.rb +23 -12
- data/lib/active_record/tasks/mysql_database_tasks.rb +9 -48
- data/lib/active_record/tasks/postgresql_database_tasks.rb +10 -2
- data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
- data/lib/active_record/timestamp.rb +5 -12
- data/lib/active_record/touch_later.rb +2 -0
- data/lib/active_record/transactions.rb +9 -7
- data/lib/active_record/translation.rb +2 -0
- data/lib/active_record/type.rb +4 -1
- data/lib/active_record/type/adapter_specific_registry.rb +2 -0
- data/lib/active_record/type/date.rb +2 -0
- data/lib/active_record/type/date_time.rb +2 -0
- data/lib/active_record/type/decimal_without_scale.rb +2 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +2 -0
- data/lib/active_record/type/internal/timezone.rb +2 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +2 -4
- data/lib/active_record/type/text.rb +2 -0
- data/lib/active_record/type/time.rb +2 -0
- data/lib/active_record/type/type_map.rb +2 -0
- data/lib/active_record/type/unsigned_integer.rb +2 -0
- data/lib/active_record/type_caster.rb +2 -0
- data/lib/active_record/type_caster/connection.rb +2 -0
- data/lib/active_record/type_caster/map.rb +2 -0
- data/lib/active_record/validations.rb +2 -0
- data/lib/active_record/validations/absence.rb +2 -0
- data/lib/active_record/validations/associated.rb +2 -0
- data/lib/active_record/validations/length.rb +2 -0
- data/lib/active_record/validations/presence.rb +2 -0
- data/lib/active_record/validations/uniqueness.rb +36 -6
- data/lib/active_record/version.rb +2 -0
- data/lib/rails/generators/active_record.rb +3 -1
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
- data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration.rb +2 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -1
- data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +0 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +2 -23
- data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +0 -0
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
- metadata +25 -38
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -15
- data/lib/active_record/associations/preloader/collection_association.rb +0 -17
- data/lib/active_record/associations/preloader/has_many.rb +0 -15
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -15
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -18
- data/lib/active_record/attribute.rb +0 -240
- data/lib/active_record/attribute/user_provided_default.rb +0 -30
- data/lib/active_record/attribute_mutation_tracker.rb +0 -122
- data/lib/active_record/attribute_set.rb +0 -113
- data/lib/active_record/attribute_set/builder.rb +0 -126
- data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -10
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -59
- data/lib/active_record/type/internal/abstract_json.rb +0 -37
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Delegation # :nodoc:
|
3
5
|
module DelegateCache # :nodoc:
|
@@ -36,13 +38,12 @@ module ActiveRecord
|
|
36
38
|
# may vary depending on the klass of a relation, so we create a subclass of Relation
|
37
39
|
# for each different klass, and the delegations are compiled into that subclass only.
|
38
40
|
|
39
|
-
delegate :to_xml, :encode_with, :length, :each, :uniq, :
|
40
|
-
:[], :&, :|, :+, :-, :sample, :reverse, :compact, :in_groups, :in_groups_of,
|
41
|
+
delegate :to_xml, :encode_with, :length, :each, :uniq, :join,
|
42
|
+
:[], :&, :|, :+, :-, :sample, :reverse, :rotate, :compact, :in_groups, :in_groups_of,
|
41
43
|
:to_sentence, :to_formatted_s, :as_json,
|
42
|
-
:shuffle, :split, :index, to: :records
|
44
|
+
:shuffle, :split, :slice, :index, :rindex, to: :records
|
43
45
|
|
44
|
-
delegate :
|
45
|
-
:connection, :columns_hash, to: :klass
|
46
|
+
delegate :primary_key, :connection, to: :klass
|
46
47
|
|
47
48
|
module ClassSpecificRelation # :nodoc:
|
48
49
|
extend ActiveSupport::Concern
|
@@ -73,13 +74,6 @@ module ActiveRecord
|
|
73
74
|
end
|
74
75
|
end
|
75
76
|
end
|
76
|
-
|
77
|
-
def delegate(method, opts = {})
|
78
|
-
@delegation_mutex.synchronize do
|
79
|
-
return if method_defined?(method)
|
80
|
-
super
|
81
|
-
end
|
82
|
-
end
|
83
77
|
end
|
84
78
|
|
85
79
|
private
|
@@ -89,7 +83,8 @@ module ActiveRecord
|
|
89
83
|
self.class.delegate_to_scoped_klass(method)
|
90
84
|
scoping { @klass.public_send(method, *args, &block) }
|
91
85
|
elsif arel.respond_to?(method)
|
92
|
-
|
86
|
+
ActiveSupport::Deprecation.warn \
|
87
|
+
"Delegating #{method} to arel is deprecated and will be removed in Rails 6.0."
|
93
88
|
arel.public_send(method, *args, &block)
|
94
89
|
else
|
95
90
|
super
|
@@ -109,21 +104,9 @@ module ActiveRecord
|
|
109
104
|
end
|
110
105
|
end
|
111
106
|
|
112
|
-
def respond_to_missing?(method, include_private = false)
|
113
|
-
super || @klass.respond_to?(method, include_private) ||
|
114
|
-
arel.respond_to?(method, include_private)
|
115
|
-
end
|
116
|
-
|
117
107
|
private
|
118
|
-
|
119
|
-
|
120
|
-
if @klass.respond_to?(method)
|
121
|
-
scoping { @klass.public_send(method, *args, &block) }
|
122
|
-
elsif arel.respond_to?(method)
|
123
|
-
arel.public_send(method, *args, &block)
|
124
|
-
else
|
125
|
-
super
|
126
|
-
end
|
108
|
+
def respond_to_missing?(method, _)
|
109
|
+
super || @klass.respond_to?(method) || arel.respond_to?(method)
|
127
110
|
end
|
128
111
|
end
|
129
112
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/string/filters"
|
2
4
|
|
3
5
|
module ActiveRecord
|
@@ -86,7 +88,7 @@ module ActiveRecord
|
|
86
88
|
where(arg, *args).take!
|
87
89
|
rescue ::RangeError
|
88
90
|
raise RecordNotFound.new("Couldn't find #{@klass.name} with an out of range value",
|
89
|
-
@klass.name)
|
91
|
+
@klass.name, @klass.primary_key)
|
90
92
|
end
|
91
93
|
|
92
94
|
# Gives a record (or N records if a parameter is supplied) without any implied
|
@@ -147,8 +149,7 @@ module ActiveRecord
|
|
147
149
|
def last(limit = nil)
|
148
150
|
return find_last(limit) if loaded? || limit_value
|
149
151
|
|
150
|
-
result = limit(limit)
|
151
|
-
result.order!(arel_attribute(primary_key)) if order_values.empty? && primary_key
|
152
|
+
result = ordered_relation.limit(limit)
|
152
153
|
result = result.reverse_order!
|
153
154
|
|
154
155
|
limit ? result.reverse : result.first
|
@@ -283,7 +284,7 @@ module ActiveRecord
|
|
283
284
|
# * Hash - Finds the record that matches these +find+-style conditions
|
284
285
|
# (such as <tt>{name: 'David'}</tt>).
|
285
286
|
# * +false+ - Returns always +false+.
|
286
|
-
# * No args - Returns +false+ if the
|
287
|
+
# * No args - Returns +false+ if the relation is empty, +true+ otherwise.
|
287
288
|
#
|
288
289
|
# For more information about specifying conditions as a hash or array,
|
289
290
|
# see the Conditions section in the introduction to ActiveRecord::Base.
|
@@ -299,6 +300,7 @@ module ActiveRecord
|
|
299
300
|
# Person.exists?(name: 'David')
|
300
301
|
# Person.exists?(false)
|
301
302
|
# Person.exists?
|
303
|
+
# Person.where(name: 'Spartacus', rating: 4).exists?
|
302
304
|
def exists?(conditions = :none)
|
303
305
|
if Base === conditions
|
304
306
|
raise ArgumentError, <<-MSG.squish
|
@@ -309,14 +311,14 @@ module ActiveRecord
|
|
309
311
|
|
310
312
|
return false if !conditions || limit_value == 0
|
311
313
|
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
314
|
+
if eager_loading?
|
315
|
+
relation = apply_join_dependency(construct_join_dependency(eager_loading: false))
|
316
|
+
return relation.exists?(conditions)
|
317
|
+
end
|
316
318
|
|
317
|
-
relation = construct_relation_for_exists(
|
319
|
+
relation = construct_relation_for_exists(conditions)
|
318
320
|
|
319
|
-
connection.select_value(relation, "#{name} Exists"
|
321
|
+
skip_query_cache_if_necessary { connection.select_value(relation.arel, "#{name} Exists") } ? true : false
|
320
322
|
rescue ::RangeError
|
321
323
|
false
|
322
324
|
end
|
@@ -329,23 +331,23 @@ module ActiveRecord
|
|
329
331
|
# of results obtained should be provided in the +result_size+ argument and
|
330
332
|
# the expected number of results should be provided in the +expected_size+
|
331
333
|
# argument.
|
332
|
-
def raise_record_not_found_exception!(ids = nil, result_size = nil, expected_size = nil, key = primary_key) # :nodoc:
|
333
|
-
conditions = arel.where_sql(@klass
|
334
|
+
def raise_record_not_found_exception!(ids = nil, result_size = nil, expected_size = nil, key = primary_key, not_found_ids = nil) # :nodoc:
|
335
|
+
conditions = arel.where_sql(@klass)
|
334
336
|
conditions = " [#{conditions}]" if conditions
|
335
337
|
name = @klass.name
|
336
338
|
|
337
339
|
if ids.nil?
|
338
|
-
error = "Couldn't find #{name}"
|
340
|
+
error = "Couldn't find #{name}".dup
|
339
341
|
error << " with#{conditions}" if conditions
|
340
|
-
raise RecordNotFound.new(error, name)
|
342
|
+
raise RecordNotFound.new(error, name, key)
|
341
343
|
elsif Array(ids).size == 1
|
342
344
|
error = "Couldn't find #{name} with '#{key}'=#{ids}#{conditions}"
|
343
345
|
raise RecordNotFound.new(error, name, key, ids)
|
344
346
|
else
|
345
|
-
error = "Couldn't find all #{name.pluralize} with '#{key}': "
|
346
|
-
error << "(#{ids.join(", ")})#{conditions} (found #{result_size} results, but was looking for #{expected_size})"
|
347
|
-
|
348
|
-
raise RecordNotFound.new(error, name,
|
347
|
+
error = "Couldn't find all #{name.pluralize} with '#{key}': ".dup
|
348
|
+
error << "(#{ids.join(", ")})#{conditions} (found #{result_size} results, but was looking for #{expected_size})."
|
349
|
+
error << " Couldn't find #{name.pluralize(not_found_ids.size)} with #{key.to_s.pluralize(not_found_ids.size)} #{not_found_ids.join(', ')}." if not_found_ids
|
350
|
+
raise RecordNotFound.new(error, name, key, ids)
|
349
351
|
end
|
350
352
|
end
|
351
353
|
|
@@ -365,21 +367,20 @@ module ActiveRecord
|
|
365
367
|
# preexisting join in joins_values to categorizations (by way of
|
366
368
|
# the `has_many :through` for categories).
|
367
369
|
#
|
368
|
-
join_dependency = construct_join_dependency
|
370
|
+
join_dependency = construct_join_dependency
|
369
371
|
|
370
|
-
|
371
|
-
relation
|
372
|
-
relation = apply_join_dependency(relation, join_dependency)
|
372
|
+
relation = apply_join_dependency(join_dependency)
|
373
|
+
relation._select!(join_dependency.aliases.columns)
|
373
374
|
|
374
375
|
yield relation, join_dependency
|
375
376
|
end
|
376
377
|
|
377
|
-
def construct_relation_for_exists(
|
378
|
-
relation =
|
378
|
+
def construct_relation_for_exists(conditions)
|
379
|
+
relation = except(:select, :distinct, :order)._select!(ONE_AS_ONE).limit!(1)
|
379
380
|
|
380
381
|
case conditions
|
381
382
|
when Array, Hash
|
382
|
-
relation.where!(conditions)
|
383
|
+
relation.where!(conditions)
|
383
384
|
else
|
384
385
|
relation.where!(primary_key => conditions) unless conditions == :none
|
385
386
|
end
|
@@ -387,17 +388,15 @@ module ActiveRecord
|
|
387
388
|
relation
|
388
389
|
end
|
389
390
|
|
390
|
-
def construct_join_dependency(
|
391
|
+
def construct_join_dependency(eager_loading: true)
|
391
392
|
including = eager_load_values + includes_values
|
392
|
-
ActiveRecord::Associations::JoinDependency.new(
|
393
|
-
|
394
|
-
|
395
|
-
def construct_relation_for_association_calculations
|
396
|
-
apply_join_dependency(self, construct_join_dependency(joins_values))
|
393
|
+
ActiveRecord::Associations::JoinDependency.new(
|
394
|
+
klass, table, including, alias_tracker(joins_values), eager_loading: eager_loading
|
395
|
+
)
|
397
396
|
end
|
398
397
|
|
399
|
-
def apply_join_dependency(
|
400
|
-
relation =
|
398
|
+
def apply_join_dependency(join_dependency = construct_join_dependency)
|
399
|
+
relation = except(:includes, :eager_load, :preload).joins!(join_dependency)
|
401
400
|
|
402
401
|
if using_limitable_reflections?(join_dependency.reflections)
|
403
402
|
relation
|
@@ -412,12 +411,13 @@ module ActiveRecord
|
|
412
411
|
|
413
412
|
def limited_ids_for(relation)
|
414
413
|
values = @klass.connection.columns_for_distinct(
|
415
|
-
|
414
|
+
connection.column_name_from_arel_node(arel_attribute(primary_key)),
|
415
|
+
relation.order_values
|
416
|
+
)
|
416
417
|
|
417
418
|
relation = relation.except(:select).select(values).distinct!
|
418
|
-
arel = relation.arel
|
419
419
|
|
420
|
-
id_rows = @klass.connection.select_all(arel, "SQL"
|
420
|
+
id_rows = skip_query_cache_if_necessary { @klass.connection.select_all(relation.arel, "SQL") }
|
421
421
|
id_rows.map { |row| row[primary_key] }
|
422
422
|
end
|
423
423
|
|
@@ -429,13 +429,16 @@ module ActiveRecord
|
|
429
429
|
raise UnknownPrimaryKey.new(@klass) if primary_key.nil?
|
430
430
|
|
431
431
|
expects_array = ids.first.kind_of?(Array)
|
432
|
-
return
|
432
|
+
return ids.first if expects_array && ids.first.empty?
|
433
433
|
|
434
434
|
ids = ids.flatten.compact.uniq
|
435
435
|
|
436
|
+
model_name = @klass.name
|
437
|
+
|
436
438
|
case ids.size
|
437
439
|
when 0
|
438
|
-
|
440
|
+
error_message = "Couldn't find #{model_name} without an ID"
|
441
|
+
raise RecordNotFound.new(error_message, model_name, primary_key)
|
439
442
|
when 1
|
440
443
|
result = find_one(ids.first)
|
441
444
|
expects_array ? [ result ] : result
|
@@ -443,7 +446,8 @@ module ActiveRecord
|
|
443
446
|
find_some(ids)
|
444
447
|
end
|
445
448
|
rescue ::RangeError
|
446
|
-
|
449
|
+
error_message = "Couldn't find #{model_name} with an out of range ID"
|
450
|
+
raise RecordNotFound.new(error_message, model_name, primary_key, ids)
|
447
451
|
end
|
448
452
|
|
449
453
|
def find_one(id)
|
@@ -525,11 +529,7 @@ module ActiveRecord
|
|
525
529
|
if loaded?
|
526
530
|
records[index, limit] || []
|
527
531
|
else
|
528
|
-
relation =
|
529
|
-
order(arel_attribute(primary_key).asc)
|
530
|
-
else
|
531
|
-
self
|
532
|
-
end
|
532
|
+
relation = ordered_relation
|
533
533
|
|
534
534
|
if limit_value.nil? || index < limit_value
|
535
535
|
relation = relation.offset(offset_index + index) unless index.zero?
|
@@ -544,11 +544,7 @@ module ActiveRecord
|
|
544
544
|
if loaded?
|
545
545
|
records[-index]
|
546
546
|
else
|
547
|
-
relation =
|
548
|
-
order(arel_attribute(primary_key).asc)
|
549
|
-
else
|
550
|
-
self
|
551
|
-
end
|
547
|
+
relation = ordered_relation
|
552
548
|
|
553
549
|
relation.to_a[-index]
|
554
550
|
# TODO: can be made more performant on large result sets by
|
@@ -562,5 +558,13 @@ module ActiveRecord
|
|
562
558
|
def find_last(limit)
|
563
559
|
limit ? records.last(limit) : records.last
|
564
560
|
end
|
561
|
+
|
562
|
+
def ordered_relation
|
563
|
+
if order_values.empty? && primary_key
|
564
|
+
order(arel_attribute(primary_key).asc)
|
565
|
+
else
|
566
|
+
self
|
567
|
+
end
|
568
|
+
end
|
565
569
|
end
|
566
570
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
class Relation
|
3
5
|
class FromClause # :nodoc:
|
@@ -8,14 +10,6 @@ module ActiveRecord
|
|
8
10
|
@name = name
|
9
11
|
end
|
10
12
|
|
11
|
-
def binds
|
12
|
-
if value.is_a?(Relation)
|
13
|
-
value.bound_attributes
|
14
|
-
else
|
15
|
-
[]
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
13
|
def merge(other)
|
20
14
|
self
|
21
15
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/hash/keys"
|
2
4
|
|
3
5
|
module ActiveRecord
|
@@ -110,21 +112,20 @@ module ActiveRecord
|
|
110
112
|
if other.klass == relation.klass
|
111
113
|
relation.joins!(*other.joins_values)
|
112
114
|
else
|
113
|
-
|
115
|
+
alias_tracker = nil
|
116
|
+
joins_dependency = other.joins_values.map do |join|
|
114
117
|
case join
|
115
118
|
when Hash, Symbol, Array
|
116
|
-
|
119
|
+
alias_tracker ||= other.alias_tracker
|
120
|
+
ActiveRecord::Associations::JoinDependency.new(
|
121
|
+
other.klass, other.table, join, alias_tracker
|
122
|
+
)
|
117
123
|
else
|
118
|
-
|
124
|
+
join
|
119
125
|
end
|
120
126
|
end
|
121
127
|
|
122
|
-
|
123
|
-
joins_dependency,
|
124
|
-
[])
|
125
|
-
relation.joins! rest
|
126
|
-
|
127
|
-
@relation = relation.joins join_dependency
|
128
|
+
relation.joins!(*joins_dependency)
|
128
129
|
end
|
129
130
|
end
|
130
131
|
|
@@ -132,19 +133,17 @@ module ActiveRecord
|
|
132
133
|
if other.reordering_value
|
133
134
|
# override any order specified in the original relation
|
134
135
|
relation.reorder! other.order_values
|
135
|
-
elsif other.order_values
|
136
|
+
elsif other.order_values.any?
|
136
137
|
# merge in order_values from relation
|
137
138
|
relation.order! other.order_values
|
138
139
|
end
|
139
140
|
|
140
|
-
|
141
|
+
extensions = other.extensions - relation.extensions
|
142
|
+
relation.extending!(*extensions) if extensions.any?
|
141
143
|
end
|
142
144
|
|
143
145
|
def merge_single_values
|
144
|
-
if
|
145
|
-
relation.from_clause = other.from_clause
|
146
|
-
end
|
147
|
-
relation.lock_value ||= other.lock_value
|
146
|
+
relation.lock_value ||= other.lock_value if other.lock_value
|
148
147
|
|
149
148
|
unless other.create_with_value.blank?
|
150
149
|
relation.create_with_value = (relation.create_with_value || {}).merge(other.create_with_value)
|
@@ -152,11 +151,15 @@ module ActiveRecord
|
|
152
151
|
end
|
153
152
|
|
154
153
|
def merge_clauses
|
155
|
-
|
156
|
-
|
157
|
-
other_clause = other.get_value(method)
|
158
|
-
relation.set_value(method, clause.merge(other_clause))
|
154
|
+
if relation.from_clause.empty? && !other.from_clause.empty?
|
155
|
+
relation.from_clause = other.from_clause
|
159
156
|
end
|
157
|
+
|
158
|
+
where_clause = relation.where_clause.merge(other.where_clause)
|
159
|
+
relation.where_clause = where_clause unless where_clause.empty?
|
160
|
+
|
161
|
+
having_clause = relation.having_clause.merge(other.having_clause)
|
162
|
+
relation.having_clause = having_clause unless having_clause.empty?
|
160
163
|
end
|
161
164
|
end
|
162
165
|
end
|
@@ -1,27 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
class PredicateBuilder # :nodoc:
|
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"
|
10
|
-
|
11
5
|
delegate :resolve_column_aliases, to: :table
|
12
6
|
|
13
7
|
def initialize(table)
|
14
8
|
@table = table
|
15
9
|
@handlers = []
|
16
10
|
|
17
|
-
register_handler(BasicObject, BasicObjectHandler.new)
|
11
|
+
register_handler(BasicObject, BasicObjectHandler.new(self))
|
18
12
|
register_handler(Base, BaseHandler.new(self))
|
19
|
-
register_handler(Range, RangeHandler.new)
|
20
|
-
register_handler(RangeHandler::RangeWithBinds, RangeHandler.new)
|
13
|
+
register_handler(Range, RangeHandler.new(self))
|
21
14
|
register_handler(Relation, RelationHandler.new)
|
22
15
|
register_handler(Array, ArrayHandler.new(self))
|
23
|
-
register_handler(
|
24
|
-
register_handler(PolymorphicArrayValue, PolymorphicArrayHandler.new(self))
|
16
|
+
register_handler(Set, ArrayHandler.new(self))
|
25
17
|
end
|
26
18
|
|
27
19
|
def build_from_hash(attributes)
|
@@ -29,11 +21,6 @@ module ActiveRecord
|
|
29
21
|
expand_from_hash(attributes)
|
30
22
|
end
|
31
23
|
|
32
|
-
def create_binds(attributes)
|
33
|
-
attributes = convert_dot_notation_to_hash(attributes)
|
34
|
-
create_binds_for_hash(attributes)
|
35
|
-
end
|
36
|
-
|
37
24
|
def self.references(attributes)
|
38
25
|
attributes.map do |key, value|
|
39
26
|
if value.is_a?(Hash)
|
@@ -64,8 +51,11 @@ module ActiveRecord
|
|
64
51
|
handler_for(value).call(attribute, value)
|
65
52
|
end
|
66
53
|
|
67
|
-
|
68
|
-
|
54
|
+
def build_bind_attribute(column_name, value)
|
55
|
+
attr = Relation::QueryAttribute.new(column_name.to_s, value, table.type(column_name))
|
56
|
+
Arel::Nodes::BindParam.new(attr)
|
57
|
+
end
|
58
|
+
|
69
59
|
protected
|
70
60
|
|
71
61
|
attr_reader :table
|
@@ -76,56 +66,34 @@ module ActiveRecord
|
|
76
66
|
attributes.flat_map do |key, value|
|
77
67
|
if value.is_a?(Hash) && !table.has_column?(key)
|
78
68
|
associated_predicate_builder(key).expand_from_hash(value)
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
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
|
69
|
+
elsif table.associated_with?(key)
|
70
|
+
# Find the foreign key when using queries such as:
|
71
|
+
# Post.where(author: author)
|
72
|
+
#
|
73
|
+
# For polymorphic relationships, find the foreign key and type:
|
74
|
+
# PriceEstimate.where(estimate_of: treasure)
|
75
|
+
associated_table = table.associated_table(key)
|
76
|
+
if associated_table.polymorphic_association?
|
77
|
+
case value.is_a?(Array) ? value.first : value
|
78
|
+
when Base, Relation
|
79
|
+
value = [value] unless value.is_a?(Array)
|
80
|
+
klass = PolymorphicArrayValue
|
81
|
+
end
|
108
82
|
end
|
109
83
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
result[column_name] = Arel::Nodes::BindParam.new
|
114
|
-
binds << build_bind_param(column_name, value)
|
84
|
+
klass ||= AssociationQueryValue
|
85
|
+
queries = klass.new(associated_table, value).queries.map do |query|
|
86
|
+
expand_from_hash(query).reduce(&:and)
|
115
87
|
end
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
if table.associated_with?(column_name)
|
124
|
-
result[column_name] = AssociationQueryHandler.value_for(table, column_name, value)
|
88
|
+
queries.reduce(&:or)
|
89
|
+
# FIXME: Deprecate this and provide a public API to force equality
|
90
|
+
elsif (value.is_a?(Range) || value.is_a?(Array)) &&
|
91
|
+
table.type(key.to_s).respond_to?(:subtype)
|
92
|
+
BasicObjectHandler.new(self).call(table.arel_attribute(key), value)
|
93
|
+
else
|
94
|
+
build(table.arel_attribute(key), value)
|
125
95
|
end
|
126
96
|
end
|
127
|
-
|
128
|
-
[result, binds]
|
129
97
|
end
|
130
98
|
|
131
99
|
private
|
@@ -153,19 +121,14 @@ module ActiveRecord
|
|
153
121
|
def handler_for(object)
|
154
122
|
@handlers.detect { |klass, _| klass === object }.last
|
155
123
|
end
|
156
|
-
|
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
|
170
124
|
end
|
171
125
|
end
|
126
|
+
|
127
|
+
require "active_record/relation/predicate_builder/array_handler"
|
128
|
+
require "active_record/relation/predicate_builder/base_handler"
|
129
|
+
require "active_record/relation/predicate_builder/basic_object_handler"
|
130
|
+
require "active_record/relation/predicate_builder/range_handler"
|
131
|
+
require "active_record/relation/predicate_builder/relation_handler"
|
132
|
+
|
133
|
+
require "active_record/relation/predicate_builder/association_query_value"
|
134
|
+
require "active_record/relation/predicate_builder/polymorphic_array_value"
|