activerecord 5.1.7 → 5.2.4.3
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 +4 -4
- data/CHANGELOG.md +556 -685
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -5
- data/examples/performance.rb +2 -0
- data/examples/simple.rb +2 -0
- data/lib/active_record.rb +11 -4
- data/lib/active_record/aggregations.rb +6 -5
- data/lib/active_record/association_relation.rb +7 -5
- data/lib/active_record/associations.rb +40 -63
- data/lib/active_record/associations/alias_tracker.rb +19 -27
- data/lib/active_record/associations/association.rb +41 -37
- data/lib/active_record/associations/association_scope.rb +38 -50
- data/lib/active_record/associations/belongs_to_association.rb +27 -8
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -8
- data/lib/active_record/associations/builder/association.rb +4 -7
- data/lib/active_record/associations/builder/belongs_to.rb +12 -4
- data/lib/active_record/associations/builder/collection_association.rb +3 -3
- 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 +59 -47
- data/lib/active_record/associations/collection_proxy.rb +20 -49
- data/lib/active_record/associations/foreign_association.rb +2 -0
- data/lib/active_record/associations/has_many_association.rb +12 -1
- data/lib/active_record/associations/has_many_through_association.rb +36 -30
- data/lib/active_record/associations/has_one_association.rb +12 -1
- data/lib/active_record/associations/has_one_through_association.rb +13 -8
- data/lib/active_record/associations/join_dependency.rb +48 -93
- data/lib/active_record/associations/join_dependency/join_association.rb +39 -63
- data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
- data/lib/active_record/associations/join_dependency/join_part.rb +9 -9
- data/lib/active_record/associations/preloader.rb +18 -38
- data/lib/active_record/associations/preloader/association.rb +45 -61
- data/lib/active_record/associations/preloader/through_association.rb +71 -79
- data/lib/active_record/associations/singular_association.rb +14 -16
- data/lib/active_record/associations/through_association.rb +26 -11
- data/lib/active_record/attribute_assignment.rb +2 -5
- data/lib/active_record/attribute_decorators.rb +3 -2
- data/lib/active_record/attribute_methods.rb +65 -24
- data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
- data/lib/active_record/attribute_methods/dirty.rb +30 -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 +9 -3
- 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 +6 -5
- data/lib/active_record/autosave_association.rb +35 -19
- data/lib/active_record/base.rb +2 -0
- data/lib/active_record/callbacks.rb +8 -6
- 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 +12 -8
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +139 -41
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +174 -33
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +15 -5
- data/lib/active_record/connection_adapters/abstract/quoting.rb +13 -31
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +14 -5
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +64 -6
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +152 -81
- data/lib/active_record/connection_adapters/abstract/transaction.rb +66 -21
- data/lib/active_record/connection_adapters/abstract_adapter.rb +84 -97
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +92 -165
- 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 +13 -2
- data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +47 -2
- 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 -10
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +30 -30
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +106 -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 +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +2 -0
- 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.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +2 -0
- 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 +4 -2
- 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 +18 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +24 -11
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +233 -111
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +57 -73
- data/lib/active_record/connection_adapters/schema_cache.rb +4 -2
- 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 +22 -0
- 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 +75 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +81 -94
- 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 +41 -61
- data/lib/active_record/counter_cache.rb +10 -3
- data/lib/active_record/define_callbacks.rb +5 -3
- data/lib/active_record/dynamic_matchers.rb +9 -9
- data/lib/active_record/enum.rb +18 -13
- data/lib/active_record/errors.rb +42 -3
- 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 +67 -60
- data/lib/active_record/gem_version.rb +5 -3
- data/lib/active_record/inheritance.rb +49 -19
- 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 +14 -17
- data/lib/active_record/locking/pessimistic.rb +9 -6
- data/lib/active_record/log_subscriber.rb +43 -0
- data/lib/active_record/migration.rb +189 -139
- data/lib/active_record/migration/command_recorder.rb +11 -9
- data/lib/active_record/migration/compatibility.rb +47 -9
- data/lib/active_record/migration/join_table.rb +2 -0
- data/lib/active_record/model_schema.rb +16 -21
- 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 +167 -16
- data/lib/active_record/query_cache.rb +6 -8
- data/lib/active_record/querying.rb +4 -2
- data/lib/active_record/railtie.rb +62 -6
- 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 +46 -36
- data/lib/active_record/readonly_attributes.rb +3 -2
- data/lib/active_record/reflection.rb +108 -194
- data/lib/active_record/relation.rb +120 -214
- 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 +45 -19
- data/lib/active_record/relation/delegation.rb +45 -27
- data/lib/active_record/relation/finder_methods.rb +75 -76
- data/lib/active_record/relation/from_clause.rb +2 -8
- data/lib/active_record/relation/merger.rb +53 -23
- data/lib/active_record/relation/predicate_builder.rb +60 -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 +56 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +26 -9
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
- data/lib/active_record/relation/query_attribute.rb +28 -2
- data/lib/active_record/relation/query_methods.rb +128 -99
- data/lib/active_record/relation/record_fetch_warning.rb +2 -0
- data/lib/active_record/relation/spawn_methods.rb +4 -2
- data/lib/active_record/relation/where_clause.rb +65 -68
- data/lib/active_record/relation/where_clause_factory.rb +5 -48
- data/lib/active_record/result.rb +2 -0
- data/lib/active_record/runtime_registry.rb +2 -0
- data/lib/active_record/sanitization.rb +129 -121
- data/lib/active_record/schema.rb +4 -2
- data/lib/active_record/schema_dumper.rb +36 -26
- data/lib/active_record/schema_migration.rb +2 -0
- data/lib/active_record/scoping.rb +9 -8
- data/lib/active_record/scoping/default.rb +8 -9
- data/lib/active_record/scoping/named.rb +23 -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 +23 -13
- data/lib/active_record/store.rb +3 -1
- data/lib/active_record/suppressor.rb +2 -0
- data/lib/active_record/table_metadata.rb +12 -3
- data/lib/active_record/tasks/database_tasks.rb +25 -14
- 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 +6 -6
- data/lib/active_record/touch_later.rb +2 -0
- data/lib/active_record/transactions.rb +33 -28
- 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 -0
- 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 +3 -1
- 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 +35 -5
- 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 +23 -36
- 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
|
require "active_support/core_ext/array/wrap"
|
2
4
|
|
3
5
|
module ActiveRecord
|
@@ -17,7 +19,6 @@ module ActiveRecord
|
|
17
19
|
# HasManyThroughAssociation + ThroughAssociation
|
18
20
|
class Association #:nodoc:
|
19
21
|
attr_reader :owner, :target, :reflection
|
20
|
-
attr_accessor :inversed
|
21
22
|
|
22
23
|
delegate :options, to: :reflection
|
23
24
|
|
@@ -30,14 +31,6 @@ module ActiveRecord
|
|
30
31
|
reset_scope
|
31
32
|
end
|
32
33
|
|
33
|
-
# Returns the name of the table of the associated class:
|
34
|
-
#
|
35
|
-
# post.comments.aliased_table_name # => "comments"
|
36
|
-
#
|
37
|
-
def aliased_table_name
|
38
|
-
klass.table_name
|
39
|
-
end
|
40
|
-
|
41
34
|
# Resets the \loaded flag to +false+ and sets the \target to +nil+.
|
42
35
|
def reset
|
43
36
|
@loaded = false
|
@@ -73,7 +66,7 @@ module ActiveRecord
|
|
73
66
|
#
|
74
67
|
# Note that if the target has not been loaded, it is not considered stale.
|
75
68
|
def stale_target?
|
76
|
-
|
69
|
+
!@inversed && loaded? && @stale_state != stale_state
|
77
70
|
end
|
78
71
|
|
79
72
|
# Sets the target of this association to <tt>\target</tt>, and the \loaded flag to +true+.
|
@@ -94,7 +87,7 @@ module ActiveRecord
|
|
94
87
|
# actually gets built.
|
95
88
|
def association_scope
|
96
89
|
if klass
|
97
|
-
@association_scope ||= AssociationScope.scope(self
|
90
|
+
@association_scope ||= AssociationScope.scope(self)
|
98
91
|
end
|
99
92
|
end
|
100
93
|
|
@@ -104,23 +97,32 @@ module ActiveRecord
|
|
104
97
|
|
105
98
|
# Set the inverse association, if possible
|
106
99
|
def set_inverse_instance(record)
|
107
|
-
if
|
108
|
-
inverse
|
109
|
-
|
110
|
-
|
100
|
+
if inverse = inverse_association_for(record)
|
101
|
+
inverse.inversed_from(owner)
|
102
|
+
end
|
103
|
+
record
|
104
|
+
end
|
105
|
+
|
106
|
+
def set_inverse_instance_from_queries(record)
|
107
|
+
if inverse = inverse_association_for(record)
|
108
|
+
inverse.inversed_from_queries(owner)
|
111
109
|
end
|
112
110
|
record
|
113
111
|
end
|
114
112
|
|
115
113
|
# Remove the inverse association, if possible
|
116
114
|
def remove_inverse_instance(record)
|
117
|
-
if
|
118
|
-
inverse
|
119
|
-
inverse.target = nil
|
120
|
-
inverse.inversed = false
|
115
|
+
if inverse = inverse_association_for(record)
|
116
|
+
inverse.inversed_from(nil)
|
121
117
|
end
|
122
118
|
end
|
123
119
|
|
120
|
+
def inversed_from(record)
|
121
|
+
self.target = record
|
122
|
+
@inversed = !!record
|
123
|
+
end
|
124
|
+
alias :inversed_from_queries :inversed_from
|
125
|
+
|
124
126
|
# Returns the class of the target. belongs_to polymorphic overrides this to look at the
|
125
127
|
# polymorphic_type field on the owner.
|
126
128
|
def klass
|
@@ -130,14 +132,14 @@ module ActiveRecord
|
|
130
132
|
# Can be overridden (i.e. in ThroughAssociation) to merge in other scopes (i.e. the
|
131
133
|
# through association's scope)
|
132
134
|
def target_scope
|
133
|
-
AssociationRelation.create(klass,
|
135
|
+
AssociationRelation.create(klass, self).merge!(klass.all)
|
134
136
|
end
|
135
137
|
|
136
138
|
def extensions
|
137
139
|
extensions = klass.default_extensions | reflection.extensions
|
138
140
|
|
139
|
-
if
|
140
|
-
extensions |= klass.unscoped
|
141
|
+
if reflection.scope
|
142
|
+
extensions |= reflection.scope_for(klass.unscoped, owner).extensions
|
141
143
|
end
|
142
144
|
|
143
145
|
extensions
|
@@ -162,17 +164,9 @@ module ActiveRecord
|
|
162
164
|
reset
|
163
165
|
end
|
164
166
|
|
165
|
-
|
166
|
-
if sql.respond_to?(:to_proc)
|
167
|
-
owner.instance_exec(record, &sql)
|
168
|
-
else
|
169
|
-
sql
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
# We can't dump @reflection since it contains the scope proc
|
167
|
+
# We can't dump @reflection and @through_reflection since it contains the scope proc
|
174
168
|
def marshal_dump
|
175
|
-
ivars = (instance_variables - [:@reflection]).map { |name| [name, instance_variable_get(name)] }
|
169
|
+
ivars = (instance_variables - [:@reflection, :@through_reflection]).map { |name| [name, instance_variable_get(name)] }
|
176
170
|
[@reflection.name, ivars]
|
177
171
|
end
|
178
172
|
|
@@ -187,8 +181,8 @@ module ActiveRecord
|
|
187
181
|
skip_assign = [reflection.foreign_key, reflection.type].compact
|
188
182
|
assigned_keys = record.changed_attribute_names_to_save
|
189
183
|
assigned_keys += except_from_scope_attributes.keys.map(&:to_s)
|
190
|
-
attributes =
|
191
|
-
record.
|
184
|
+
attributes = scope_for_create.except!(*(assigned_keys - skip_assign))
|
185
|
+
record.send(:_assign_attributes, attributes) if attributes.any?
|
192
186
|
set_inverse_instance(record)
|
193
187
|
end
|
194
188
|
|
@@ -201,6 +195,9 @@ module ActiveRecord
|
|
201
195
|
end
|
202
196
|
|
203
197
|
private
|
198
|
+
def scope_for_create
|
199
|
+
scope.scope_for_create
|
200
|
+
end
|
204
201
|
|
205
202
|
def find_target?
|
206
203
|
!loaded? && (!owner.new_record? || foreign_key_present?) && klass
|
@@ -212,8 +209,8 @@ module ActiveRecord
|
|
212
209
|
if (reflection.has_one? || reflection.collection?) && !options[:through]
|
213
210
|
attributes[reflection.foreign_key] = owner[reflection.active_record_primary_key]
|
214
211
|
|
215
|
-
if reflection.
|
216
|
-
attributes[reflection.type] = owner.class.
|
212
|
+
if reflection.type
|
213
|
+
attributes[reflection.type] = owner.class.polymorphic_name
|
217
214
|
end
|
218
215
|
end
|
219
216
|
|
@@ -251,6 +248,12 @@ module ActiveRecord
|
|
251
248
|
end
|
252
249
|
end
|
253
250
|
|
251
|
+
def inverse_association_for(record)
|
252
|
+
if invertible_for?(record)
|
253
|
+
record.association(inverse_reflection_for(record).name)
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
254
257
|
# Can be redefined by subclasses, notably polymorphic belongs_to
|
255
258
|
# The record parameter is necessary to support polymorphic inverses as we must check for
|
256
259
|
# the association in the specific class of the record.
|
@@ -280,11 +283,12 @@ module ActiveRecord
|
|
280
283
|
def build_record(attributes)
|
281
284
|
reflection.build_association(attributes) do |record|
|
282
285
|
initialize_attributes(record, attributes)
|
286
|
+
yield(record) if block_given?
|
283
287
|
end
|
284
288
|
end
|
285
289
|
|
286
290
|
# Returns true if statement cache should be skipped on the association reader.
|
287
|
-
def skip_statement_cache?
|
291
|
+
def skip_statement_cache?(scope)
|
288
292
|
reflection.has_scope? ||
|
289
293
|
scope.eager_loading? ||
|
290
294
|
klass.scope_attributes? ||
|
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Associations
|
3
5
|
class AssociationScope #:nodoc:
|
4
|
-
def self.scope(association
|
5
|
-
INSTANCE.scope(association
|
6
|
+
def self.scope(association)
|
7
|
+
INSTANCE.scope(association)
|
6
8
|
end
|
7
9
|
|
8
10
|
def self.create(&block)
|
@@ -16,20 +18,15 @@ module ActiveRecord
|
|
16
18
|
|
17
19
|
INSTANCE = create
|
18
20
|
|
19
|
-
def scope(association
|
21
|
+
def scope(association)
|
20
22
|
klass = association.klass
|
21
23
|
reflection = association.reflection
|
22
24
|
scope = klass.unscoped
|
23
25
|
owner = association.owner
|
24
|
-
|
25
|
-
chain_head, chain_tail = get_chain(reflection, association, alias_tracker)
|
26
|
+
chain = get_chain(reflection, association, scope.alias_tracker)
|
26
27
|
|
27
28
|
scope.extending! reflection.extensions
|
28
|
-
add_constraints(scope, owner,
|
29
|
-
end
|
30
|
-
|
31
|
-
def join_type
|
32
|
-
Arel::Nodes::InnerJoin
|
29
|
+
add_constraints(scope, owner, chain)
|
33
30
|
end
|
34
31
|
|
35
32
|
def self.get_bind_values(owner, chain)
|
@@ -38,12 +35,12 @@ module ActiveRecord
|
|
38
35
|
|
39
36
|
binds << last_reflection.join_id_for(owner)
|
40
37
|
if last_reflection.type
|
41
|
-
binds << owner.class.
|
38
|
+
binds << owner.class.polymorphic_name
|
42
39
|
end
|
43
40
|
|
44
41
|
chain.each_cons(2).each do |reflection, next_reflection|
|
45
42
|
if reflection.type
|
46
|
-
binds << next_reflection.klass.
|
43
|
+
binds << next_reflection.klass.polymorphic_name
|
47
44
|
end
|
48
45
|
end
|
49
46
|
binds
|
@@ -57,19 +54,20 @@ module ActiveRecord
|
|
57
54
|
|
58
55
|
private
|
59
56
|
def join(table, constraint)
|
60
|
-
table.create_join(table, table.create_on(constraint)
|
57
|
+
table.create_join(table, table.create_on(constraint))
|
61
58
|
end
|
62
59
|
|
63
|
-
def last_chain_scope(scope,
|
60
|
+
def last_chain_scope(scope, reflection, owner)
|
64
61
|
join_keys = reflection.join_keys
|
65
62
|
key = join_keys.key
|
66
63
|
foreign_key = join_keys.foreign_key
|
67
64
|
|
65
|
+
table = reflection.aliased_table
|
68
66
|
value = transform_value(owner[foreign_key])
|
69
67
|
scope = apply_scope(scope, table, key, value)
|
70
68
|
|
71
69
|
if reflection.type
|
72
|
-
polymorphic_type = transform_value(owner.class.
|
70
|
+
polymorphic_type = transform_value(owner.class.polymorphic_name)
|
73
71
|
scope = apply_scope(scope, table, reflection.type, polymorphic_type)
|
74
72
|
end
|
75
73
|
|
@@ -80,15 +78,17 @@ module ActiveRecord
|
|
80
78
|
value_transformation.call(value)
|
81
79
|
end
|
82
80
|
|
83
|
-
def next_chain_scope(scope,
|
81
|
+
def next_chain_scope(scope, reflection, next_reflection)
|
84
82
|
join_keys = reflection.join_keys
|
85
83
|
key = join_keys.key
|
86
84
|
foreign_key = join_keys.foreign_key
|
87
85
|
|
86
|
+
table = reflection.aliased_table
|
87
|
+
foreign_table = next_reflection.aliased_table
|
88
88
|
constraint = table[key].eq(foreign_table[foreign_key])
|
89
89
|
|
90
90
|
if reflection.type
|
91
|
-
value = transform_value(next_reflection.klass.
|
91
|
+
value = transform_value(next_reflection.klass.polymorphic_name)
|
92
92
|
scope = apply_scope(scope, table, reflection.type, value)
|
93
93
|
end
|
94
94
|
|
@@ -96,12 +96,11 @@ module ActiveRecord
|
|
96
96
|
end
|
97
97
|
|
98
98
|
class ReflectionProxy < SimpleDelegator # :nodoc:
|
99
|
-
|
100
|
-
attr_reader :alias_name
|
99
|
+
attr_reader :aliased_table
|
101
100
|
|
102
|
-
def initialize(reflection,
|
101
|
+
def initialize(reflection, aliased_table)
|
103
102
|
super(reflection)
|
104
|
-
@
|
103
|
+
@aliased_table = aliased_table
|
105
104
|
end
|
106
105
|
|
107
106
|
def all_includes; nil; end
|
@@ -109,43 +108,34 @@ module ActiveRecord
|
|
109
108
|
|
110
109
|
def get_chain(reflection, association, tracker)
|
111
110
|
name = reflection.name
|
112
|
-
|
113
|
-
previous_reflection = runtime_reflection
|
111
|
+
chain = [Reflection::RuntimeReflection.new(reflection, association)]
|
114
112
|
reflection.chain.drop(1).each do |refl|
|
115
|
-
|
113
|
+
aliased_table = tracker.aliased_table_for(
|
116
114
|
refl.table_name,
|
117
115
|
refl.alias_candidate(name),
|
118
116
|
refl.klass.type_caster
|
119
117
|
)
|
120
|
-
|
121
|
-
previous_reflection.next = proxy
|
122
|
-
previous_reflection = proxy
|
118
|
+
chain << ReflectionProxy.new(refl, aliased_table)
|
123
119
|
end
|
124
|
-
|
120
|
+
chain
|
125
121
|
end
|
126
122
|
|
127
|
-
def add_constraints(scope, owner,
|
128
|
-
|
129
|
-
table = owner_reflection.alias_name
|
130
|
-
scope = last_chain_scope(scope, table, owner_reflection, owner)
|
131
|
-
|
132
|
-
reflection = chain_head
|
133
|
-
while reflection
|
134
|
-
table = reflection.alias_name
|
135
|
-
next_reflection = reflection.next
|
123
|
+
def add_constraints(scope, owner, chain)
|
124
|
+
scope = last_chain_scope(scope, chain.last, owner)
|
136
125
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
end
|
126
|
+
chain.each_cons(2) do |reflection, next_reflection|
|
127
|
+
scope = next_chain_scope(scope, reflection, next_reflection)
|
128
|
+
end
|
141
129
|
|
130
|
+
chain_head = chain.first
|
131
|
+
chain.reverse_each do |reflection|
|
142
132
|
# Exclude the scope of the association itself, because that
|
143
133
|
# was already merged in the #scope method.
|
144
134
|
reflection.constraints.each do |scope_chain_item|
|
145
|
-
item = eval_scope(reflection
|
135
|
+
item = eval_scope(reflection, scope_chain_item, owner)
|
146
136
|
|
147
|
-
if scope_chain_item ==
|
148
|
-
scope.merge! item.except(:where, :includes)
|
137
|
+
if scope_chain_item == chain_head.scope
|
138
|
+
scope.merge! item.except(:where, :includes, :unscope, :order)
|
149
139
|
end
|
150
140
|
|
151
141
|
reflection.all_includes do
|
@@ -154,10 +144,8 @@ module ActiveRecord
|
|
154
144
|
|
155
145
|
scope.unscope!(*item.unscope_values)
|
156
146
|
scope.where_clause += item.where_clause
|
157
|
-
scope.order_values
|
147
|
+
scope.order_values = item.order_values | scope.order_values
|
158
148
|
end
|
159
|
-
|
160
|
-
reflection = next_reflection
|
161
149
|
end
|
162
150
|
|
163
151
|
scope
|
@@ -171,9 +159,9 @@ module ActiveRecord
|
|
171
159
|
end
|
172
160
|
end
|
173
161
|
|
174
|
-
def eval_scope(
|
175
|
-
|
176
|
-
|
162
|
+
def eval_scope(reflection, scope, owner)
|
163
|
+
relation = reflection.build_scope(reflection.aliased_table)
|
164
|
+
relation.instance_exec(owner, &scope) || relation
|
177
165
|
end
|
178
166
|
end
|
179
167
|
end
|
@@ -1,26 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
|
-
# = Active Record Belongs To Association
|
3
4
|
module Associations
|
5
|
+
# = Active Record Belongs To Association
|
4
6
|
class BelongsToAssociation < SingularAssociation #:nodoc:
|
5
7
|
def handle_dependency
|
6
|
-
|
8
|
+
return unless load_target
|
9
|
+
|
10
|
+
case options[:dependent]
|
11
|
+
when :destroy
|
12
|
+
target.destroy
|
13
|
+
raise ActiveRecord::Rollback unless target.destroyed?
|
14
|
+
else
|
15
|
+
target.send(options[:dependent])
|
16
|
+
end
|
7
17
|
end
|
8
18
|
|
9
19
|
def replace(record)
|
10
20
|
if record
|
11
21
|
raise_on_type_mismatch!(record)
|
12
22
|
update_counters_on_replace(record)
|
13
|
-
replace_keys(record)
|
14
23
|
set_inverse_instance(record)
|
15
24
|
@updated = true
|
16
25
|
else
|
17
26
|
decrement_counters
|
18
|
-
remove_keys
|
19
27
|
end
|
20
28
|
|
29
|
+
replace_keys(record)
|
30
|
+
|
21
31
|
self.target = record
|
22
32
|
end
|
23
33
|
|
34
|
+
def inversed_from(record)
|
35
|
+
replace_keys(record)
|
36
|
+
super
|
37
|
+
end
|
38
|
+
|
24
39
|
def default(&block)
|
25
40
|
writer(owner.instance_exec(&block)) if reader.nil?
|
26
41
|
end
|
@@ -42,6 +57,10 @@ module ActiveRecord
|
|
42
57
|
update_counters(1)
|
43
58
|
end
|
44
59
|
|
60
|
+
def target_changed?
|
61
|
+
owner.saved_change_to_attribute?(reflection.foreign_key)
|
62
|
+
end
|
63
|
+
|
45
64
|
private
|
46
65
|
|
47
66
|
def update_counters(by)
|
@@ -72,15 +91,15 @@ module ActiveRecord
|
|
72
91
|
|
73
92
|
# Checks whether record is different to the current target, without loading it
|
74
93
|
def different_target?(record)
|
75
|
-
record.
|
94
|
+
record._read_attribute(primary_key(record)) != owner._read_attribute(reflection.foreign_key)
|
76
95
|
end
|
77
96
|
|
78
97
|
def replace_keys(record)
|
79
|
-
owner[reflection.foreign_key] = record._read_attribute(
|
98
|
+
owner[reflection.foreign_key] = record ? record._read_attribute(primary_key(record)) : nil
|
80
99
|
end
|
81
100
|
|
82
|
-
def
|
83
|
-
|
101
|
+
def primary_key(record)
|
102
|
+
reflection.association_primary_key(record.class)
|
84
103
|
end
|
85
104
|
|
86
105
|
def foreign_key_present?
|
@@ -1,22 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
|
-
# = Active Record Belongs To Polymorphic Association
|
3
4
|
module Associations
|
5
|
+
# = Active Record Belongs To Polymorphic Association
|
4
6
|
class BelongsToPolymorphicAssociation < BelongsToAssociation #:nodoc:
|
5
7
|
def klass
|
6
8
|
type = owner[reflection.foreign_type]
|
7
9
|
type.presence && type.constantize
|
8
10
|
end
|
9
11
|
|
10
|
-
|
12
|
+
def target_changed?
|
13
|
+
super || owner.saved_change_to_attribute?(reflection.foreign_type)
|
14
|
+
end
|
11
15
|
|
16
|
+
private
|
12
17
|
def replace_keys(record)
|
13
18
|
super
|
14
|
-
owner[reflection.foreign_type] = record.class.
|
15
|
-
end
|
16
|
-
|
17
|
-
def remove_keys
|
18
|
-
super
|
19
|
-
owner[reflection.foreign_type] = nil
|
19
|
+
owner[reflection.foreign_type] = record ? record.class.polymorphic_name : nil
|
20
20
|
end
|
21
21
|
|
22
22
|
def different_target?(record)
|