activerecord 5.0.7.2 → 5.1.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 +389 -2252
- 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.rb +20 -20
- data/lib/active_record/aggregations.rb +244 -244
- data/lib/active_record/association_relation.rb +5 -5
- data/lib/active_record/associations.rb +1579 -1569
- data/lib/active_record/associations/alias_tracker.rb +1 -1
- data/lib/active_record/associations/association.rb +23 -15
- data/lib/active_record/associations/association_scope.rb +83 -81
- data/lib/active_record/associations/belongs_to_association.rb +0 -1
- data/lib/active_record/associations/builder/belongs_to.rb +16 -14
- 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 +74 -241
- data/lib/active_record/associations/collection_proxy.rb +144 -70
- data/lib/active_record/associations/has_many_association.rb +15 -19
- data/lib/active_record/associations/has_many_through_association.rb +12 -5
- data/lib/active_record/associations/has_one_association.rb +22 -28
- data/lib/active_record/associations/has_one_through_association.rb +5 -1
- data/lib/active_record/associations/join_dependency.rb +117 -115
- data/lib/active_record/associations/join_dependency/join_association.rb +16 -13
- 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/preloader.rb +94 -94
- data/lib/active_record/associations/preloader/association.rb +87 -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 +34 -41
- data/lib/active_record/associations/singular_association.rb +8 -25
- data/lib/active_record/associations/through_association.rb +3 -6
- data/lib/active_record/attribute.rb +98 -71
- data/lib/active_record/attribute/user_provided_default.rb +4 -2
- data/lib/active_record/attribute_assignment.rb +61 -61
- data/lib/active_record/attribute_decorators.rb +35 -13
- data/lib/active_record/attribute_methods.rb +56 -65
- data/lib/active_record/attribute_methods/before_type_cast.rb +7 -7
- data/lib/active_record/attribute_methods/dirty.rb +216 -34
- data/lib/active_record/attribute_methods/primary_key.rb +78 -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 +36 -30
- data/lib/active_record/attribute_mutation_tracker.rb +53 -10
- data/lib/active_record/attribute_set.rb +9 -6
- data/lib/active_record/attribute_set/builder.rb +41 -49
- data/lib/active_record/attribute_set/yaml_encoder.rb +41 -0
- data/lib/active_record/attributes.rb +21 -21
- data/lib/active_record/autosave_association.rb +13 -13
- data/lib/active_record/base.rb +24 -22
- data/lib/active_record/callbacks.rb +52 -14
- data/lib/active_record/coders/yaml_column.rb +9 -11
- data/lib/active_record/collection_cache_key.rb +6 -17
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +320 -278
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +1 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +22 -34
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +31 -27
- data/lib/active_record/connection_adapters/abstract/quoting.rb +44 -57
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +9 -19
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +78 -79
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +53 -41
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +99 -93
- data/lib/active_record/connection_adapters/abstract/transaction.rb +1 -5
- data/lib/active_record/connection_adapters/abstract_adapter.rb +156 -128
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +424 -382
- data/lib/active_record/connection_adapters/column.rb +27 -5
- 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 +45 -43
- 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 +49 -31
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +5 -6
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +24 -26
- data/lib/active_record/connection_adapters/postgresql/column.rb +1 -28
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +46 -35
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +22 -21
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +9 -9
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
- 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/enum.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +16 -16
- 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 +28 -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/quoting.rb +38 -36
- 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 +161 -170
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +179 -152
- 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 -20
- 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_adapter.rb +187 -130
- 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 +110 -93
- data/lib/active_record/counter_cache.rb +62 -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 +58 -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 +3 -3
- 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 +64 -56
- data/lib/active_record/locking/pessimistic.rb +10 -1
- data/lib/active_record/log_subscriber.rb +29 -29
- data/lib/active_record/migration.rb +155 -172
- data/lib/active_record/migration/command_recorder.rb +94 -94
- data/lib/active_record/migration/compatibility.rb +76 -37
- data/lib/active_record/migration/join_table.rb +6 -6
- data/lib/active_record/model_schema.rb +85 -119
- data/lib/active_record/nested_attributes.rb +200 -199
- data/lib/active_record/null_relation.rb +10 -33
- data/lib/active_record/persistence.rb +45 -38
- data/lib/active_record/query_cache.rb +4 -8
- data/lib/active_record/querying.rb +2 -3
- 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 +125 -140
- 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 +79 -96
- data/lib/active_record/relation.rb +72 -115
- data/lib/active_record/relation/batches.rb +87 -58
- data/lib/active_record/relation/batches/batch_enumerator.rb +1 -1
- data/lib/active_record/relation/calculations.rb +154 -160
- data/lib/active_record/relation/delegation.rb +30 -29
- data/lib/active_record/relation/finder_methods.rb +195 -226
- data/lib/active_record/relation/merger.rb +58 -62
- data/lib/active_record/relation/predicate_builder.rb +92 -89
- 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/query_attribute.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +247 -295
- 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 +79 -65
- data/lib/active_record/relation/where_clause_factory.rb +47 -8
- data/lib/active_record/result.rb +29 -31
- data/lib/active_record/runtime_registry.rb +3 -3
- data/lib/active_record/sanitization.rb +182 -197
- data/lib/active_record/schema.rb +3 -3
- data/lib/active_record/schema_dumper.rb +14 -37
- data/lib/active_record/schema_migration.rb +3 -3
- data/lib/active_record/scoping.rb +9 -10
- data/lib/active_record/scoping/default.rb +87 -91
- data/lib/active_record/scoping/named.rb +16 -28
- 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 +72 -65
- data/lib/active_record/tasks/mysql_database_tasks.rb +75 -72
- data/lib/active_record/tasks/postgresql_database_tasks.rb +53 -48
- data/lib/active_record/tasks/sqlite_database_tasks.rb +18 -16
- data/lib/active_record/timestamp.rb +39 -25
- data/lib/active_record/touch_later.rb +1 -2
- data/lib/active_record/transactions.rb +98 -110
- data/lib/active_record/type.rb +17 -13
- data/lib/active_record/type/adapter_specific_registry.rb +46 -42
- data/lib/active_record/type/decimal_without_scale.rb +9 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +3 -3
- data/lib/active_record/type/serialized.rb +8 -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_caster.rb +2 -2
- data/lib/active_record/type_caster/connection.rb +8 -6
- data/lib/active_record/type_caster/map.rb +3 -1
- data/lib/active_record/validations.rb +4 -4
- 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/version.rb +1 -1
- data/lib/rails/generators/active_record.rb +4 -4
- data/lib/rails/generators/active_record/migration.rb +2 -2
- data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -34
- data/lib/rails/generators/active_record/model/model_generator.rb +9 -9
- metadata +22 -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/array/wrap"
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
module Associations
|
@@ -19,7 +19,7 @@ module ActiveRecord
|
|
19
19
|
attr_reader :owner, :target, :reflection
|
20
20
|
attr_accessor :inversed
|
21
21
|
|
22
|
-
delegate :options, :
|
22
|
+
delegate :options, to: :reflection
|
23
23
|
|
24
24
|
def initialize(owner, reflection)
|
25
25
|
reflection.check_validity!
|
@@ -112,6 +112,15 @@ module ActiveRecord
|
|
112
112
|
record
|
113
113
|
end
|
114
114
|
|
115
|
+
# Remove the inverse association, if possible
|
116
|
+
def remove_inverse_instance(record)
|
117
|
+
if invertible_for?(record)
|
118
|
+
inverse = record.association(inverse_reflection_for(record).name)
|
119
|
+
inverse.target = nil
|
120
|
+
inverse.inversed = false
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
115
124
|
# Returns the class of the target. belongs_to polymorphic overrides this to look at the
|
116
125
|
# polymorphic_type field on the owner.
|
117
126
|
def klass
|
@@ -124,16 +133,6 @@ module ActiveRecord
|
|
124
133
|
AssociationRelation.create(klass, klass.arel_table, klass.predicate_builder, self).merge!(klass.all)
|
125
134
|
end
|
126
135
|
|
127
|
-
def extensions
|
128
|
-
extensions = klass.default_extensions | reflection.extensions
|
129
|
-
|
130
|
-
if scope = reflection.scope
|
131
|
-
extensions |= klass.unscoped.instance_exec(owner, &scope).extensions
|
132
|
-
end
|
133
|
-
|
134
|
-
extensions
|
135
|
-
end
|
136
|
-
|
137
136
|
# Loads the \target if needed and returns it.
|
138
137
|
#
|
139
138
|
# This method is abstract in the sense that it relies on +find_target+,
|
@@ -176,13 +175,21 @@ module ActiveRecord
|
|
176
175
|
def initialize_attributes(record, except_from_scope_attributes = nil) #:nodoc:
|
177
176
|
except_from_scope_attributes ||= {}
|
178
177
|
skip_assign = [reflection.foreign_key, reflection.type].compact
|
179
|
-
assigned_keys = record.
|
178
|
+
assigned_keys = record.changed_attribute_names_to_save
|
180
179
|
assigned_keys += except_from_scope_attributes.keys.map(&:to_s)
|
181
180
|
attributes = create_scope.except(*(assigned_keys - skip_assign))
|
182
181
|
record.assign_attributes(attributes)
|
183
182
|
set_inverse_instance(record)
|
184
183
|
end
|
185
184
|
|
185
|
+
def create(attributes = {}, &block)
|
186
|
+
_create_record(attributes, &block)
|
187
|
+
end
|
188
|
+
|
189
|
+
def create!(attributes = {}, &block)
|
190
|
+
_create_record(attributes, true, &block)
|
191
|
+
end
|
192
|
+
|
186
193
|
private
|
187
194
|
|
188
195
|
def find_target?
|
@@ -227,7 +234,8 @@ module ActiveRecord
|
|
227
234
|
unless record.is_a?(reflection.klass)
|
228
235
|
fresh_class = reflection.class_name.safe_constantize
|
229
236
|
unless fresh_class && record.is_a?(fresh_class)
|
230
|
-
message = "#{reflection.class_name}(##{reflection.klass.object_id}) expected,
|
237
|
+
message = "#{reflection.class_name}(##{reflection.klass.object_id}) expected, "\
|
238
|
+
"got #{record.inspect} which is an instance of #{record.class}(##{record.class.object_id})"
|
231
239
|
raise ActiveRecord::AssociationTypeMismatch, message
|
232
240
|
end
|
233
241
|
end
|
@@ -255,7 +263,7 @@ module ActiveRecord
|
|
255
263
|
# so that when stale_state is different from the value stored on the last find_target,
|
256
264
|
# the target is stale.
|
257
265
|
#
|
258
|
-
# This is only relevant to certain associations, which is why it returns nil by default.
|
266
|
+
# This is only relevant to certain associations, which is why it returns +nil+ by default.
|
259
267
|
def stale_state
|
260
268
|
end
|
261
269
|
|
@@ -24,7 +24,7 @@ module ActiveRecord
|
|
24
24
|
alias_tracker = AliasTracker.create connection, association.klass.table_name, klass.type_caster
|
25
25
|
chain_head, chain_tail = get_chain(reflection, association, alias_tracker)
|
26
26
|
|
27
|
-
scope.extending! reflection.
|
27
|
+
scope.extending! Array(reflection.options[:extend])
|
28
28
|
add_constraints(scope, owner, klass, reflection, chain_head, chain_tail)
|
29
29
|
end
|
30
30
|
|
@@ -49,118 +49,120 @@ module ActiveRecord
|
|
49
49
|
binds
|
50
50
|
end
|
51
51
|
|
52
|
+
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
53
|
+
# Workaround for Ruby 2.2 "private attribute?" warning.
|
52
54
|
protected
|
53
55
|
|
54
|
-
|
56
|
+
attr_reader :value_transformation
|
55
57
|
|
56
58
|
private
|
57
|
-
|
58
|
-
|
59
|
-
|
59
|
+
def join(table, constraint)
|
60
|
+
table.create_join(table, table.create_on(constraint), join_type)
|
61
|
+
end
|
60
62
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
63
|
+
def last_chain_scope(scope, table, reflection, owner, association_klass)
|
64
|
+
join_keys = reflection.join_keys(association_klass)
|
65
|
+
key = join_keys.key
|
66
|
+
foreign_key = join_keys.foreign_key
|
65
67
|
|
66
|
-
|
67
|
-
|
68
|
+
value = transform_value(owner[foreign_key])
|
69
|
+
scope = scope.where(table.name => { key => value })
|
68
70
|
|
69
|
-
|
70
|
-
|
71
|
-
|
71
|
+
if reflection.type
|
72
|
+
polymorphic_type = transform_value(owner.class.base_class.name)
|
73
|
+
scope = scope.where(table.name => { reflection.type => polymorphic_type })
|
74
|
+
end
|
75
|
+
|
76
|
+
scope
|
72
77
|
end
|
73
78
|
|
74
|
-
|
75
|
-
|
79
|
+
def transform_value(value)
|
80
|
+
value_transformation.call(value)
|
81
|
+
end
|
76
82
|
|
77
|
-
|
78
|
-
|
79
|
-
|
83
|
+
def next_chain_scope(scope, table, reflection, association_klass, foreign_table, next_reflection)
|
84
|
+
join_keys = reflection.join_keys(association_klass)
|
85
|
+
key = join_keys.key
|
86
|
+
foreign_key = join_keys.foreign_key
|
80
87
|
|
81
|
-
|
82
|
-
join_keys = reflection.join_keys(association_klass)
|
83
|
-
key = join_keys.key
|
84
|
-
foreign_key = join_keys.foreign_key
|
88
|
+
constraint = table[key].eq(foreign_table[foreign_key])
|
85
89
|
|
86
|
-
|
90
|
+
if reflection.type
|
91
|
+
value = transform_value(next_reflection.klass.base_class.name)
|
92
|
+
scope = scope.where(table.name => { reflection.type => value })
|
93
|
+
end
|
87
94
|
|
88
|
-
|
89
|
-
value = transform_value(next_reflection.klass.base_class.name)
|
90
|
-
scope = scope.where(table.name => { reflection.type => value })
|
95
|
+
scope = scope.joins(join(foreign_table, constraint))
|
91
96
|
end
|
92
97
|
|
93
|
-
|
94
|
-
|
98
|
+
class ReflectionProxy < SimpleDelegator # :nodoc:
|
99
|
+
attr_accessor :next
|
100
|
+
attr_reader :alias_name
|
95
101
|
|
96
|
-
|
97
|
-
|
98
|
-
|
102
|
+
def initialize(reflection, alias_name)
|
103
|
+
super(reflection)
|
104
|
+
@alias_name = alias_name
|
105
|
+
end
|
99
106
|
|
100
|
-
|
101
|
-
super(reflection)
|
102
|
-
@alias_name = alias_name
|
107
|
+
def all_includes; nil; end
|
103
108
|
end
|
104
109
|
|
105
|
-
def
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
previous_reflection
|
116
|
-
previous_reflection = proxy
|
110
|
+
def get_chain(reflection, association, tracker)
|
111
|
+
name = reflection.name
|
112
|
+
runtime_reflection = Reflection::RuntimeReflection.new(reflection, association)
|
113
|
+
previous_reflection = runtime_reflection
|
114
|
+
reflection.chain.drop(1).each do |refl|
|
115
|
+
alias_name = tracker.aliased_table_for(refl.table_name, refl.alias_candidate(name))
|
116
|
+
proxy = ReflectionProxy.new(refl, alias_name)
|
117
|
+
previous_reflection.next = proxy
|
118
|
+
previous_reflection = proxy
|
119
|
+
end
|
120
|
+
[runtime_reflection, previous_reflection]
|
117
121
|
end
|
118
|
-
[runtime_reflection, previous_reflection]
|
119
|
-
end
|
120
|
-
|
121
|
-
def add_constraints(scope, owner, association_klass, refl, chain_head, chain_tail)
|
122
|
-
owner_reflection = chain_tail
|
123
|
-
table = owner_reflection.alias_name
|
124
|
-
scope = last_chain_scope(scope, table, owner_reflection, owner, association_klass)
|
125
122
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
123
|
+
def add_constraints(scope, owner, association_klass, refl, chain_head, chain_tail)
|
124
|
+
owner_reflection = chain_tail
|
125
|
+
table = owner_reflection.alias_name
|
126
|
+
scope = last_chain_scope(scope, table, owner_reflection, owner, association_klass)
|
130
127
|
|
131
|
-
|
128
|
+
reflection = chain_head
|
129
|
+
while reflection
|
130
|
+
table = reflection.alias_name
|
132
131
|
next_reflection = reflection.next
|
133
|
-
foreign_table = next_reflection.alias_name
|
134
|
-
scope = next_chain_scope(scope, table, reflection, association_klass, foreign_table, next_reflection)
|
135
|
-
end
|
136
|
-
|
137
|
-
# Exclude the scope of the association itself, because that
|
138
|
-
# was already merged in the #scope method.
|
139
|
-
reflection.constraints.each do |scope_chain_item|
|
140
|
-
item = eval_scope(reflection.klass, scope_chain_item, owner)
|
141
132
|
|
142
|
-
|
143
|
-
|
133
|
+
unless reflection == chain_tail
|
134
|
+
foreign_table = next_reflection.alias_name
|
135
|
+
scope = next_chain_scope(scope, table, reflection, association_klass, foreign_table, next_reflection)
|
144
136
|
end
|
145
137
|
|
146
|
-
|
147
|
-
|
138
|
+
# Exclude the scope of the association itself, because that
|
139
|
+
# was already merged in the #scope method.
|
140
|
+
reflection.constraints.each do |scope_chain_item|
|
141
|
+
item = eval_scope(reflection.klass, table, scope_chain_item, owner)
|
142
|
+
|
143
|
+
if scope_chain_item == refl.scope
|
144
|
+
scope.merge! item.except(:where, :includes)
|
145
|
+
end
|
146
|
+
|
147
|
+
reflection.all_includes do
|
148
|
+
scope.includes! item.includes_values
|
149
|
+
end
|
150
|
+
|
151
|
+
scope.unscope!(*item.unscope_values)
|
152
|
+
scope.where_clause += item.where_clause
|
153
|
+
scope.order_values |= item.order_values
|
148
154
|
end
|
149
155
|
|
150
|
-
|
151
|
-
scope.where_clause += item.where_clause
|
152
|
-
scope.order_values |= item.order_values
|
156
|
+
reflection = next_reflection
|
153
157
|
end
|
154
158
|
|
155
|
-
|
159
|
+
scope
|
156
160
|
end
|
157
161
|
|
158
|
-
scope
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
klass.unscoped.instance_exec(owner, &scope)
|
163
|
-
end
|
162
|
+
def eval_scope(klass, table, scope, owner)
|
163
|
+
predicate_builder = PredicateBuilder.new(TableMetadata.new(klass, table))
|
164
|
+
ActiveRecord::Relation.create(klass, table, predicate_builder).instance_exec(owner, &scope)
|
165
|
+
end
|
164
166
|
end
|
165
167
|
end
|
166
168
|
end
|
@@ -35,17 +35,17 @@ module ActiveRecord::Associations::Builder # :nodoc:
|
|
35
35
|
@_after_create_counter_called = false
|
36
36
|
elsif (@_after_replace_counter_called ||= false)
|
37
37
|
@_after_replace_counter_called = false
|
38
|
-
elsif
|
38
|
+
elsif saved_change_to_attribute?(foreign_key) && !new_record?
|
39
39
|
if reflection.polymorphic?
|
40
|
-
model =
|
41
|
-
model_was =
|
40
|
+
model = attribute_in_database(reflection.foreign_type).try(:constantize)
|
41
|
+
model_was = attribute_before_last_save(reflection.foreign_type).try(:constantize)
|
42
42
|
else
|
43
43
|
model = reflection.klass
|
44
44
|
model_was = reflection.klass
|
45
45
|
end
|
46
46
|
|
47
|
-
foreign_key_was =
|
48
|
-
foreign_key =
|
47
|
+
foreign_key_was = attribute_before_last_save foreign_key
|
48
|
+
foreign_key = attribute_in_database foreign_key
|
49
49
|
|
50
50
|
if foreign_key && model.respond_to?(:increment_counter)
|
51
51
|
model.increment_counter(cache_column, foreign_key)
|
@@ -70,14 +70,16 @@ module ActiveRecord::Associations::Builder # :nodoc:
|
|
70
70
|
klass.attr_readonly cache_column if klass && klass.respond_to?(:attr_readonly)
|
71
71
|
end
|
72
72
|
|
73
|
-
def self.touch_record(o, foreign_key, name, touch, touch_method) # :nodoc:
|
74
|
-
old_foreign_id =
|
73
|
+
def self.touch_record(o, changes, foreign_key, name, touch, touch_method) # :nodoc:
|
74
|
+
old_foreign_id = changes[foreign_key] && changes[foreign_key].first
|
75
75
|
|
76
76
|
if old_foreign_id
|
77
77
|
association = o.association(name)
|
78
78
|
reflection = association.reflection
|
79
79
|
if reflection.polymorphic?
|
80
|
-
|
80
|
+
foreign_type = reflection.foreign_type
|
81
|
+
klass = changes[foreign_type] && changes[foreign_type].first || o.public_send(foreign_type)
|
82
|
+
klass = klass.constantize
|
81
83
|
else
|
82
84
|
klass = association.klass
|
83
85
|
end
|
@@ -107,13 +109,13 @@ module ActiveRecord::Associations::Builder # :nodoc:
|
|
107
109
|
n = reflection.name
|
108
110
|
touch = reflection.options[:touch]
|
109
111
|
|
110
|
-
callback = lambda { |record|
|
111
|
-
BelongsTo.touch_record(record, foreign_key, n, touch, belongs_to_touch_method)
|
112
|
-
}
|
112
|
+
callback = lambda { |changes_method| lambda { |record|
|
113
|
+
BelongsTo.touch_record(record, record.send(changes_method), foreign_key, n, touch, belongs_to_touch_method)
|
114
|
+
}}
|
113
115
|
|
114
|
-
model.after_save callback, if: :
|
115
|
-
model.after_touch callback
|
116
|
-
model.after_destroy callback
|
116
|
+
model.after_save callback.(:saved_changes), if: :saved_changes?
|
117
|
+
model.after_touch callback.(:changes_to_save)
|
118
|
+
model.after_destroy callback.(:changes_to_save)
|
117
119
|
end
|
118
120
|
|
119
121
|
def self.add_destroy_callbacks(model, reflection)
|
@@ -1,10 +1,9 @@
|
|
1
1
|
# This class is inherited by the has_many and has_many_and_belongs_to_many association classes
|
2
2
|
|
3
|
-
require
|
3
|
+
require "active_record/associations"
|
4
4
|
|
5
5
|
module ActiveRecord::Associations::Builder # :nodoc:
|
6
6
|
class CollectionAssociation < Association #:nodoc:
|
7
|
-
|
8
7
|
CALLBACKS = [:before_add, :after_add, :before_remove, :after_remove]
|
9
8
|
|
10
9
|
def self.valid_options(options)
|
@@ -16,9 +16,9 @@ module ActiveRecord::Associations::Builder # :nodoc:
|
|
16
16
|
|
17
17
|
private
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
def klass
|
20
|
+
@lhs_class.send(:compute_type, @rhs_class_name)
|
21
|
+
end
|
22
22
|
end
|
23
23
|
|
24
24
|
def self.build(lhs_class, name, options)
|
@@ -28,7 +28,7 @@ module ActiveRecord::Associations::Builder # :nodoc:
|
|
28
28
|
class_name = options.fetch(:class_name) {
|
29
29
|
name.to_s.camelize.singularize
|
30
30
|
}
|
31
|
-
KnownClass.new lhs_class, class_name
|
31
|
+
KnownClass.new lhs_class, class_name.to_s
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
@@ -78,9 +78,9 @@ module ActiveRecord::Associations::Builder # :nodoc:
|
|
78
78
|
|
79
79
|
private
|
80
80
|
|
81
|
-
|
82
|
-
|
83
|
-
|
81
|
+
def self.suppress_composite_primary_key(pk)
|
82
|
+
pk unless pk.is_a?(Array)
|
83
|
+
end
|
84
84
|
}
|
85
85
|
|
86
86
|
join_model.name = "HABTM_#{association_name.to_s.camelize}"
|
@@ -94,7 +94,7 @@ module ActiveRecord::Associations::Builder # :nodoc:
|
|
94
94
|
|
95
95
|
def middle_reflection(join_model)
|
96
96
|
middle_name = [lhs_model.name.downcase.pluralize,
|
97
|
-
association_name].join(
|
97
|
+
association_name].join("_".freeze).gsub("::".freeze, "_".freeze).to_sym
|
98
98
|
middle_options = middle_options join_model
|
99
99
|
|
100
100
|
HasMany.create_reflection(lhs_model,
|
@@ -105,29 +105,29 @@ module ActiveRecord::Associations::Builder # :nodoc:
|
|
105
105
|
|
106
106
|
private
|
107
107
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
108
|
+
def middle_options(join_model)
|
109
|
+
middle_options = {}
|
110
|
+
middle_options[:class_name] = "#{lhs_model.name}::#{join_model.name}"
|
111
|
+
middle_options[:source] = join_model.left_reflection.name
|
112
|
+
if options.key? :foreign_key
|
113
|
+
middle_options[:foreign_key] = options[:foreign_key]
|
114
|
+
end
|
115
|
+
middle_options
|
114
116
|
end
|
115
|
-
middle_options
|
116
|
-
end
|
117
117
|
|
118
|
-
|
119
|
-
|
118
|
+
def belongs_to_options(options)
|
119
|
+
rhs_options = {}
|
120
120
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
121
|
+
if options.key? :class_name
|
122
|
+
rhs_options[:foreign_key] = options[:class_name].to_s.foreign_key
|
123
|
+
rhs_options[:class_name] = options[:class_name]
|
124
|
+
end
|
125
125
|
|
126
|
-
|
127
|
-
|
128
|
-
|
126
|
+
if options.key? :association_foreign_key
|
127
|
+
rhs_options[:foreign_key] = options[:association_foreign_key]
|
128
|
+
end
|
129
129
|
|
130
|
-
|
131
|
-
|
130
|
+
rhs_options
|
131
|
+
end
|
132
132
|
end
|
133
133
|
end
|