@@ -29,12 +29,33 @@ def <<(*args)
29
29
return concat ( docs ) if docs . size > 1
30
30
if doc = docs . first
31
31
append ( doc ) do
32
- _base . add_to_set ( foreign_key => doc . public_send ( _association . primary_key ) )
33
- if child_persistable? ( doc )
34
- doc . save
32
+ # We ignore the changes to the value for the foreign key in the
33
+ # changed_attributes hash in this block of code for two reasons:
34
+ #
35
+ # 1) The add_to_set method deletes the value for the foreign
36
+ # key in the changed_attributes hash, but if we enter this
37
+ # method with a value for the foreign key in the
38
+ # changed_attributes hash, then we want it to exist outside
39
+ # this method as well. It's used later on in the Syncable
40
+ # module to set the inverse foreign keys.
41
+ # 2) The reset_unloaded method accesses the value for the foreign
42
+ # key on _base, which causes it to get added to the
43
+ # changed_attributes hash. This happens because when reading
44
+ # a "resizable" attribute, it is automatically added to the
45
+ # changed_attributes hash. This is true only for the foreign
46
+ # key value for HABTM associations as the other associations
47
+ # use strings for their foreign key values. For consistency
48
+ # with the other associations, we ignore this addition to
49
+ # the changed_attributes hash.
50
+ # See MONGOID-4843 for a longer discussion about this.
51
+ reset_foreign_key_changes do
52
+ _base . add_to_set ( foreign_key => doc . public_send ( _association . primary_key ) )
53
+
54
+ if child_persistable? ( doc )
55
+ doc . save
56
+ end
57
+ reset_unloaded
35
58
end
36
- reset_unloaded
37
- clear_foreign_key_changes
38
59
end
39
60
end
40
61
unsynced ( _base , foreign_key ) and self
@@ -202,21 +223,30 @@ def unscoped
202
223
203
224
# Clears the foreign key from the changed_attributes hash.
204
225
#
205
- # reset_unloaded accesses the value for the foreign key on
206
- # _base, which causes it to get added to the changed_attributes
207
- # hash. This happens because when reading a "resizable" attribute
208
- # it is automatically added to the changed_attributes hash.
209
- # this is true only for the foreign key value for HABTM associations
210
- # as the other associations use strings for their foreign key values.
211
- # For consistency with the other associations, we clear the foreign
212
- # key from the changed_attributes hash.
213
- # See MONGOID-4843 for a longer discussion about this.
226
+ # This is, in general, used to clear the foreign key from the
227
+ # changed_attributes hash for consistency with the other referenced
228
+ # associations.
214
229
#
215
230
# @api private
216
231
def clear_foreign_key_changes
217
232
_base . changed_attributes . delete ( foreign_key )
218
233
end
219
234
235
+ # Reset the value in the changed_attributes hash for the foreign key
236
+ # to its value before executing the given block.
237
+ #
238
+ # @api private
239
+ def reset_foreign_key_changes
240
+ if _base . changed_attributes . key? ( foreign_key )
241
+ fk = _base . changed_attributes [ foreign_key ] . dup
242
+ yield if block_given?
243
+ _base . changed_attributes [ foreign_key ] = fk
244
+ else
245
+ yield if block_given?
246
+ clear_foreign_key_changes
247
+ end
248
+ end
249
+
220
250
# Appends the document to the target array, updating the index on the
221
251
# document at the same time.
222
252
#
0 commit comments