File tree Expand file tree Collapse file tree 4 files changed +56
-2
lines changed Expand file tree Collapse file tree 4 files changed +56
-2
lines changed Original file line number Diff line number Diff line change @@ -385,11 +385,35 @@ def touch_atomic_updates(field = nil)
385
385
updates = atomic_updates
386
386
return { } unless atomic_updates . key? ( "$set" )
387
387
touches = { }
388
+ wanted_keys = %w( updated_at u_at )
389
+ # TODO this permits field to be passed as an empty string in which case
390
+ # it is ignored, get rid of this behavior.
391
+ if field . present?
392
+ wanted_keys << field . to_s
393
+ end
388
394
updates [ "$set" ] . each_pair do |key , value |
389
- key_regex = /updated_at|u_at#{ "|" + field if field . present? } /
390
- touches . merge! ( { key => value } ) if key =~ key_regex
395
+ if wanted_keys . include? ( key . split ( '.' ) . last )
396
+ touches . update ( key => value )
397
+ end
391
398
end
392
399
{ "$set" => touches }
393
400
end
401
+
402
+ # Returns the $set atomic updates affecting the specified field.
403
+ #
404
+ # @param [ String ] field The field name.
405
+ #
406
+ # @api private
407
+ def set_field_atomic_updates ( field )
408
+ updates = atomic_updates
409
+ return { } unless atomic_updates . key? ( "$set" )
410
+ sets = { }
411
+ updates [ "$set" ] . each_pair do |key , value |
412
+ if key . split ( '.' ) . last == field
413
+ sets . update ( key => value )
414
+ end
415
+ end
416
+ { "$set" => sets }
417
+ end
394
418
end
395
419
end
Original file line number Diff line number Diff line change @@ -41,6 +41,16 @@ def touch(field = nil)
41
41
# _association.inverse_association.options but inverse_association
42
42
# seems to not always/ever be set here. See MONGOID-5014.
43
43
_parent . touch
44
+
45
+ if field
46
+ # If we are told to also touch a field, perform a separate write
47
+ # for that field. See MONGOID-5136.
48
+ # In theory we should combine the writes, which would require
49
+ # passing the fields to be updated to the parents - MONGOID-5142.
50
+ sets = set_field_atomic_updates ( field )
51
+ selector = atomic_selector
52
+ _root . collection . find ( selector ) . update_one ( positionally ( selector , sets ) , session : _session )
53
+ end
44
54
else
45
55
# If the current document is not embedded, it is composition root
46
56
# and we need to persist the write here.
Original file line number Diff line number Diff line change 132
132
include_examples 'updates the child'
133
133
include_examples 'updates the parent when :touch is true'
134
134
include_examples 'updates the parent when :touch is not set'
135
+
136
+ context 'when also updating an additional field' do
137
+ it 'persists the update to the additional field' do
138
+ entrance
139
+ update_time
140
+ entrance . touch ( :last_used_at )
141
+
142
+ entrance . reload
143
+ building . reload
144
+
145
+ # This is the assertion we want.
146
+ entrance . last_used_at . should == update_time
147
+
148
+ # Check other timestamps for good measure.
149
+ entrance . updated_at . should == update_time
150
+ building . updated_at . should == update_time
151
+ end
152
+ end
135
153
end
136
154
137
155
context "when the document is referenced" do
Original file line number Diff line number Diff line change @@ -16,6 +16,8 @@ class Entrance
16
16
include Mongoid ::Timestamps
17
17
18
18
embedded_in :building
19
+
20
+ field :last_used_at , type : Time
19
21
end
20
22
21
23
class Floor
You can’t perform that action at this time.
0 commit comments