composite_primary_keys 13.0.7 → 14.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/History.rdoc +894 -910
- data/README.rdoc +182 -181
- data/lib/composite_primary_keys/associations/collection_association.rb +31 -31
- data/lib/composite_primary_keys/associations/{join_association.rb → join_dependency.rb} +137 -137
- data/lib/composite_primary_keys/associations/preloader/association.rb +68 -61
- data/lib/composite_primary_keys/associations/through_association.rb +25 -24
- data/lib/composite_primary_keys/autosave_association.rb +60 -60
- data/lib/composite_primary_keys/base.rb +141 -137
- data/lib/composite_primary_keys/composite_arrays.rb +86 -86
- data/lib/composite_primary_keys/composite_predicates.rb +71 -120
- data/lib/composite_primary_keys/persistence.rb +96 -83
- data/lib/composite_primary_keys/relation/calculations.rb +110 -104
- data/lib/composite_primary_keys/relation.rb +2 -2
- data/lib/composite_primary_keys/validations/uniqueness.rb +31 -31
- data/lib/composite_primary_keys/version.rb +8 -8
- data/lib/composite_primary_keys.rb +118 -118
- data/test/abstract_unit.rb +118 -114
- data/test/fixtures/department.rb +16 -16
- data/test/fixtures/membership.rb +8 -8
- data/test/fixtures/room_assignment.rb +13 -13
- data/test/test_associations.rb +372 -372
- data/test/test_composite_arrays.rb +38 -38
- data/test/test_create.rb +218 -219
- data/test/test_predicates.rb +60 -130
- metadata +7 -7
@@ -1,137 +1,137 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
module Associations
|
3
|
-
class JoinDependency
|
4
|
-
|
5
|
-
class JoinAssociation < JoinPart # :nodoc:
|
6
|
-
private
|
7
|
-
def append_constraints(join, constraints)
|
8
|
-
if join.is_a?(Arel::Nodes::StringJoin)
|
9
|
-
join_string = Arel::Nodes::And.new(constraints.unshift join.left)
|
10
|
-
join.left = Arel.sql(base_klass.connection.visitor.compile(join_string))
|
11
|
-
else
|
12
|
-
right = join.right
|
13
|
-
# CPK
|
14
|
-
if right.expr.
|
15
|
-
right.expr = Arel::Nodes::And.new(constraints)
|
16
|
-
else
|
17
|
-
right.expr = Arel::Nodes::And.new(constraints.unshift right.expr)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
class Aliases # :nodoc:
|
24
|
-
def column_alias(node, column)
|
25
|
-
# CPK
|
26
|
-
#@alias_cache[node][column]
|
27
|
-
if column.kind_of?(Array)
|
28
|
-
column.map do |a_column|
|
29
|
-
@alias_cache[node][a_column]
|
30
|
-
end
|
31
|
-
else
|
32
|
-
@alias_cache[node][column]
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def instantiate(result_set, strict_loading_value, &block)
|
38
|
-
primary_key = aliases.column_alias(join_root, join_root.primary_key)
|
39
|
-
|
40
|
-
seen = Hash.new { |i, parent|
|
41
|
-
i[parent] = Hash.new { |j, child_class|
|
42
|
-
j[child_class] = {}
|
43
|
-
}
|
44
|
-
}.compare_by_identity
|
45
|
-
|
46
|
-
model_cache = Hash.new { |h, klass| h[klass] = {} }
|
47
|
-
parents = model_cache[join_root]
|
48
|
-
|
49
|
-
column_aliases = aliases.column_aliases(join_root)
|
50
|
-
column_names = []
|
51
|
-
|
52
|
-
result_set.columns.each do |name|
|
53
|
-
column_names << name unless /\At\d+_r\d+\z/.match?(name)
|
54
|
-
end
|
55
|
-
|
56
|
-
if column_names.empty?
|
57
|
-
column_types = {}
|
58
|
-
else
|
59
|
-
column_types = result_set.column_types
|
60
|
-
unless column_types.empty?
|
61
|
-
attribute_types = join_root.attribute_types
|
62
|
-
column_types = column_types.slice(*column_names).delete_if { |k, _| attribute_types.key?(k) }
|
63
|
-
end
|
64
|
-
column_aliases += column_names.map! { |name| Aliases::Column.new(name, name) }
|
65
|
-
end
|
66
|
-
|
67
|
-
message_bus = ActiveSupport::Notifications.instrumenter
|
68
|
-
|
69
|
-
payload = {
|
70
|
-
record_count: result_set.length,
|
71
|
-
class_name: join_root.base_klass.name
|
72
|
-
}
|
73
|
-
|
74
|
-
message_bus.instrument("instantiation.active_record", payload) do
|
75
|
-
result_set.each { |row_hash|
|
76
|
-
# CPK
|
77
|
-
# parent_key = primary_key ? row_hash[primary_key] : row_hash
|
78
|
-
parent_key = if primary_key.kind_of?(Array)
|
79
|
-
primary_key.map {|key| row_hash[key]}
|
80
|
-
else
|
81
|
-
primary_key ? row_hash[primary_key] : row_hash
|
82
|
-
end
|
83
|
-
|
84
|
-
parent = parents[parent_key] ||= join_root.instantiate(row_hash, column_aliases, column_types, &block)
|
85
|
-
construct(parent, join_root, row_hash, seen, model_cache, strict_loading_value)
|
86
|
-
}
|
87
|
-
end
|
88
|
-
|
89
|
-
parents.values
|
90
|
-
end
|
91
|
-
|
92
|
-
def construct(ar_parent, parent, row, seen, model_cache, strict_loading_value)
|
93
|
-
return if ar_parent.nil?
|
94
|
-
|
95
|
-
parent.children.each do |node|
|
96
|
-
if node.reflection.collection?
|
97
|
-
other = ar_parent.association(node.reflection.name)
|
98
|
-
other.loaded!
|
99
|
-
elsif ar_parent.association_cached?(node.reflection.name)
|
100
|
-
model = ar_parent.association(node.reflection.name).target
|
101
|
-
construct(model, node, row, seen, model_cache, strict_loading_value)
|
102
|
-
next
|
103
|
-
end
|
104
|
-
|
105
|
-
key = aliases.column_alias(node, node.primary_key)
|
106
|
-
# CPK
|
107
|
-
if key.is_a?(Array)
|
108
|
-
id = Array(key).map do |column_alias|
|
109
|
-
row[column_alias]
|
110
|
-
end
|
111
|
-
# At least the first value in the key has to be set. Should we require all values to be set?
|
112
|
-
id = nil if id.first.nil?
|
113
|
-
else # original
|
114
|
-
id = row[key]
|
115
|
-
end
|
116
|
-
|
117
|
-
if id.nil?
|
118
|
-
nil_association = ar_parent.association(node.reflection.name)
|
119
|
-
nil_association.loaded!
|
120
|
-
next
|
121
|
-
end
|
122
|
-
|
123
|
-
model = seen[ar_parent][node][id]
|
124
|
-
|
125
|
-
if model
|
126
|
-
construct(model, node, row, seen, model_cache, strict_loading_value)
|
127
|
-
else
|
128
|
-
model = construct_model(ar_parent, node, row, model_cache, id, strict_loading_value)
|
129
|
-
|
130
|
-
seen[ar_parent][node][id] = model
|
131
|
-
construct(model, node, row, seen, model_cache, strict_loading_value)
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
1
|
+
module ActiveRecord
|
2
|
+
module Associations
|
3
|
+
class JoinDependency
|
4
|
+
|
5
|
+
class JoinAssociation < JoinPart # :nodoc:
|
6
|
+
private
|
7
|
+
def append_constraints(join, constraints)
|
8
|
+
if join.is_a?(Arel::Nodes::StringJoin)
|
9
|
+
join_string = Arel::Nodes::And.new(constraints.unshift join.left)
|
10
|
+
join.left = Arel.sql(base_klass.connection.visitor.compile(join_string))
|
11
|
+
else
|
12
|
+
right = join.right
|
13
|
+
# CPK
|
14
|
+
if right.expr.children.empty?
|
15
|
+
right.expr = Arel::Nodes::And.new(constraints)
|
16
|
+
else
|
17
|
+
right.expr = Arel::Nodes::And.new(constraints.unshift right.expr)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class Aliases # :nodoc:
|
24
|
+
def column_alias(node, column)
|
25
|
+
# CPK
|
26
|
+
#@alias_cache[node][column]
|
27
|
+
if column.kind_of?(Array)
|
28
|
+
column.map do |a_column|
|
29
|
+
@alias_cache[node][a_column]
|
30
|
+
end
|
31
|
+
else
|
32
|
+
@alias_cache[node][column]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def instantiate(result_set, strict_loading_value, &block)
|
38
|
+
primary_key = aliases.column_alias(join_root, join_root.primary_key)
|
39
|
+
|
40
|
+
seen = Hash.new { |i, parent|
|
41
|
+
i[parent] = Hash.new { |j, child_class|
|
42
|
+
j[child_class] = {}
|
43
|
+
}
|
44
|
+
}.compare_by_identity
|
45
|
+
|
46
|
+
model_cache = Hash.new { |h, klass| h[klass] = {} }
|
47
|
+
parents = model_cache[join_root]
|
48
|
+
|
49
|
+
column_aliases = aliases.column_aliases(join_root)
|
50
|
+
column_names = []
|
51
|
+
|
52
|
+
result_set.columns.each do |name|
|
53
|
+
column_names << name unless /\At\d+_r\d+\z/.match?(name)
|
54
|
+
end
|
55
|
+
|
56
|
+
if column_names.empty?
|
57
|
+
column_types = {}
|
58
|
+
else
|
59
|
+
column_types = result_set.column_types
|
60
|
+
unless column_types.empty?
|
61
|
+
attribute_types = join_root.attribute_types
|
62
|
+
column_types = column_types.slice(*column_names).delete_if { |k, _| attribute_types.key?(k) }
|
63
|
+
end
|
64
|
+
column_aliases += column_names.map! { |name| Aliases::Column.new(name, name) }
|
65
|
+
end
|
66
|
+
|
67
|
+
message_bus = ActiveSupport::Notifications.instrumenter
|
68
|
+
|
69
|
+
payload = {
|
70
|
+
record_count: result_set.length,
|
71
|
+
class_name: join_root.base_klass.name
|
72
|
+
}
|
73
|
+
|
74
|
+
message_bus.instrument("instantiation.active_record", payload) do
|
75
|
+
result_set.each { |row_hash|
|
76
|
+
# CPK
|
77
|
+
# parent_key = primary_key ? row_hash[primary_key] : row_hash
|
78
|
+
parent_key = if primary_key.kind_of?(Array)
|
79
|
+
primary_key.map {|key| row_hash[key]}
|
80
|
+
else
|
81
|
+
primary_key ? row_hash[primary_key] : row_hash
|
82
|
+
end
|
83
|
+
|
84
|
+
parent = parents[parent_key] ||= join_root.instantiate(row_hash, column_aliases, column_types, &block)
|
85
|
+
construct(parent, join_root, row_hash, seen, model_cache, strict_loading_value)
|
86
|
+
}
|
87
|
+
end
|
88
|
+
|
89
|
+
parents.values
|
90
|
+
end
|
91
|
+
|
92
|
+
def construct(ar_parent, parent, row, seen, model_cache, strict_loading_value)
|
93
|
+
return if ar_parent.nil?
|
94
|
+
|
95
|
+
parent.children.each do |node|
|
96
|
+
if node.reflection.collection?
|
97
|
+
other = ar_parent.association(node.reflection.name)
|
98
|
+
other.loaded!
|
99
|
+
elsif ar_parent.association_cached?(node.reflection.name)
|
100
|
+
model = ar_parent.association(node.reflection.name).target
|
101
|
+
construct(model, node, row, seen, model_cache, strict_loading_value)
|
102
|
+
next
|
103
|
+
end
|
104
|
+
|
105
|
+
key = aliases.column_alias(node, node.primary_key)
|
106
|
+
# CPK
|
107
|
+
if key.is_a?(Array)
|
108
|
+
id = Array(key).map do |column_alias|
|
109
|
+
row[column_alias]
|
110
|
+
end
|
111
|
+
# At least the first value in the key has to be set. Should we require all values to be set?
|
112
|
+
id = nil if id.first.nil?
|
113
|
+
else # original
|
114
|
+
id = row[key]
|
115
|
+
end
|
116
|
+
|
117
|
+
if id.nil?
|
118
|
+
nil_association = ar_parent.association(node.reflection.name)
|
119
|
+
nil_association.loaded!
|
120
|
+
next
|
121
|
+
end
|
122
|
+
|
123
|
+
model = seen[ar_parent][node][id]
|
124
|
+
|
125
|
+
if model
|
126
|
+
construct(model, node, row, seen, model_cache, strict_loading_value)
|
127
|
+
else
|
128
|
+
model = construct_model(ar_parent, node, row, model_cache, id, strict_loading_value)
|
129
|
+
|
130
|
+
seen[ar_parent][node][id] = model
|
131
|
+
construct(model, node, row, seen, model_cache, strict_loading_value)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -1,61 +1,68 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
module Associations
|
3
|
-
class Preloader
|
4
|
-
class Association
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
1
|
+
module ActiveRecord
|
2
|
+
module Associations
|
3
|
+
class Preloader
|
4
|
+
class Association
|
5
|
+
|
6
|
+
class LoaderQuery
|
7
|
+
def load_records_for_keys(keys, &block)
|
8
|
+
# CPK
|
9
|
+
if association_key_name.is_a?(Array)
|
10
|
+
predicate = cpk_in_predicate(scope.klass.arel_table, association_key_name, keys)
|
11
|
+
scope.where(predicate).load(&block)
|
12
|
+
else
|
13
|
+
scope.where(association_key_name => keys).load(&block)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# TODO: is records_for needed anymore? Rails' implementation has changed significantly
|
19
|
+
def records_for(ids)
|
20
|
+
records = if association_key_name.is_a?(Array)
|
21
|
+
predicate = cpk_in_predicate(klass.arel_table, association_key_name, ids)
|
22
|
+
scope.where(predicate)
|
23
|
+
else
|
24
|
+
scope.where(association_key_name => ids)
|
25
|
+
end
|
26
|
+
records.load do |record|
|
27
|
+
# Processing only the first owner
|
28
|
+
# because the record is modified but not an owner
|
29
|
+
owner = owners_by_key[convert_key(record[association_key_name])].first
|
30
|
+
association = owner.association(reflection.name)
|
31
|
+
association.set_inverse_instance(record)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def owners_by_key
|
36
|
+
@owners_by_key ||= owners.each_with_object({}) do |owner, result|
|
37
|
+
# CPK
|
38
|
+
# key = convert_key(owner[owner_key_name])
|
39
|
+
key = if owner_key_name.is_a?(Array)
|
40
|
+
Array(owner_key_name).map do |key_name|
|
41
|
+
convert_key(owner[key_name])
|
42
|
+
end
|
43
|
+
else
|
44
|
+
convert_key(owner[owner_key_name])
|
45
|
+
end
|
46
|
+
(result[key] ||= []) << owner if key
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# TODO: is records_by_owner needed anymore? Rails' implementation has changed significantly
|
51
|
+
def records_by_owner
|
52
|
+
@records_by_owner ||= preloaded_records.each_with_object({}) do |record, result|
|
53
|
+
key = if association_key_name.is_a?(Array)
|
54
|
+
Array(record[association_key_name]).map do |key|
|
55
|
+
convert_key(key)
|
56
|
+
end
|
57
|
+
else
|
58
|
+
convert_key(record[association_key_name])
|
59
|
+
end
|
60
|
+
owners_by_key[key].each do |owner|
|
61
|
+
(result[owner] ||= []) << record
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -1,24 +1,25 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
module Associations
|
3
|
-
module ThroughAssociation
|
4
|
-
alias :original_construct_join_attributes :construct_join_attributes
|
5
|
-
|
6
|
-
def construct_join_attributes(*records)
|
7
|
-
# CPK
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
end
|
1
|
+
module ActiveRecord
|
2
|
+
module Associations
|
3
|
+
module ThroughAssociation
|
4
|
+
alias :original_construct_join_attributes :construct_join_attributes
|
5
|
+
|
6
|
+
def construct_join_attributes(*records)
|
7
|
+
# CPK
|
8
|
+
is_composite = self.source_reflection.polymorphic? ? source_reflection.active_record.composite? : source_reflection.klass.composite?
|
9
|
+
if is_composite
|
10
|
+
ensure_mutable
|
11
|
+
|
12
|
+
ids = records.map do |record|
|
13
|
+
source_reflection.association_primary_key(reflection.klass).map do |key|
|
14
|
+
record.send(key)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
cpk_in_predicate(through_association.scope.klass.arel_table, source_reflection.foreign_key, ids)
|
19
|
+
else
|
20
|
+
original_construct_join_attributes(*records)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -1,60 +1,60 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
module AutosaveAssociation
|
3
|
-
def save_has_one_association(reflection)
|
4
|
-
association = association_instance_get(reflection.name)
|
5
|
-
record = association && association.load_target
|
6
|
-
|
7
|
-
if record && !record.destroyed?
|
8
|
-
autosave = reflection.options[:autosave]
|
9
|
-
|
10
|
-
if autosave && record.marked_for_destruction?
|
11
|
-
record.destroy
|
12
|
-
elsif autosave != false
|
13
|
-
# CPK
|
14
|
-
#key = reflection.options[:primary_key] ? send(reflection.options[:primary_key]) : id
|
15
|
-
key = reflection.options[:primary_key] ? self[reflection.options[:primary_key]] : id
|
16
|
-
|
17
|
-
if (autosave && record.changed_for_autosave?) || new_record? || record_changed?(reflection, record, key)
|
18
|
-
unless reflection.through_reflection
|
19
|
-
record[reflection.foreign_key] = key
|
20
|
-
if inverse_reflection = reflection.inverse_of
|
21
|
-
record.association(inverse_reflection.name).loaded!
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
saved = record.save(validate: !autosave)
|
26
|
-
raise ActiveRecord::Rollback if !saved && autosave
|
27
|
-
saved
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def save_belongs_to_association(reflection)
|
34
|
-
association = association_instance_get(reflection.name)
|
35
|
-
return unless association && association.loaded? && !association.stale_target?
|
36
|
-
|
37
|
-
record = association.load_target
|
38
|
-
if record && !record.destroyed?
|
39
|
-
autosave = reflection.options[:autosave]
|
40
|
-
|
41
|
-
if autosave && record.marked_for_destruction?
|
42
|
-
self[reflection.foreign_key] = nil
|
43
|
-
record.destroy
|
44
|
-
elsif autosave != false
|
45
|
-
saved = record.save(validate: !autosave) if record.new_record? || (autosave && record.changed_for_autosave?)
|
46
|
-
|
47
|
-
if association.updated?
|
48
|
-
# CPK
|
49
|
-
# association_id = record.send(reflection.options[:primary_key] || :id)
|
50
|
-
association_id = reflection.options[:primary_key] ? record[reflection.options[:primary_key]] : record.id
|
51
|
-
self[reflection.foreign_key] = association_id
|
52
|
-
association.loaded!
|
53
|
-
end
|
54
|
-
|
55
|
-
saved if autosave
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
1
|
+
module ActiveRecord
|
2
|
+
module AutosaveAssociation
|
3
|
+
def save_has_one_association(reflection)
|
4
|
+
association = association_instance_get(reflection.name)
|
5
|
+
record = association && association.load_target
|
6
|
+
|
7
|
+
if record && !record.destroyed?
|
8
|
+
autosave = reflection.options[:autosave]
|
9
|
+
|
10
|
+
if autosave && record.marked_for_destruction?
|
11
|
+
record.destroy
|
12
|
+
elsif autosave != false
|
13
|
+
# CPK
|
14
|
+
#key = reflection.options[:primary_key] ? send(reflection.options[:primary_key]) : id
|
15
|
+
key = reflection.options[:primary_key] ? self[reflection.options[:primary_key]] : id
|
16
|
+
|
17
|
+
if (autosave && record.changed_for_autosave?) || new_record? || record_changed?(reflection, record, key)
|
18
|
+
unless reflection.through_reflection
|
19
|
+
record[reflection.foreign_key] = key
|
20
|
+
if inverse_reflection = reflection.inverse_of
|
21
|
+
record.association(inverse_reflection.name).loaded!
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
saved = record.save(validate: !autosave)
|
26
|
+
raise ActiveRecord::Rollback if !saved && autosave
|
27
|
+
saved
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def save_belongs_to_association(reflection)
|
34
|
+
association = association_instance_get(reflection.name)
|
35
|
+
return unless association && association.loaded? && !association.stale_target?
|
36
|
+
|
37
|
+
record = association.load_target
|
38
|
+
if record && !record.destroyed?
|
39
|
+
autosave = reflection.options[:autosave]
|
40
|
+
|
41
|
+
if autosave && record.marked_for_destruction?
|
42
|
+
self[reflection.foreign_key] = nil
|
43
|
+
record.destroy
|
44
|
+
elsif autosave != false
|
45
|
+
saved = record.save(validate: !autosave) if record.new_record? || (autosave && record.changed_for_autosave?)
|
46
|
+
|
47
|
+
if association.updated?
|
48
|
+
# CPK
|
49
|
+
# association_id = record.send(reflection.options[:primary_key] || :id)
|
50
|
+
association_id = reflection.options[:primary_key] ? record[reflection.options[:primary_key]] : record.id
|
51
|
+
self[reflection.foreign_key] = association_id
|
52
|
+
association.loaded!
|
53
|
+
end
|
54
|
+
|
55
|
+
saved if autosave
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|