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 @@ -344,11 +344,35 @@ def touch_atomic_updates(field = nil)
344
344
updates = atomic_updates
345
345
return { } unless atomic_updates . key? ( "$set" )
346
346
touches = { }
347
+ wanted_keys = %w( updated_at u_at )
348
+ # TODO this permits field to be passed as an empty string in which case
349
+ # it is ignored, get rid of this behavior.
350
+ if field . present?
351
+ wanted_keys << field . to_s
352
+ end
347
353
updates [ "$set" ] . each_pair do |key , value |
348
- key_regex = /updated_at|u_at#{ "|" + field if field . present? } /
349
- touches . merge! ( { key => value } ) if key =~ key_regex
354
+ if wanted_keys . include? ( key . split ( '.' ) . last )
355
+ touches . update ( key => value )
356
+ end
350
357
end
351
358
{ "$set" => touches }
352
359
end
360
+
361
+ # Returns the $set atomic updates affecting the specified field.
362
+ #
363
+ # @param [ String ] field The field name.
364
+ #
365
+ # @api private
366
+ def set_field_atomic_updates ( field )
367
+ updates = atomic_updates
368
+ return { } unless atomic_updates . key? ( "$set" )
369
+ sets = { }
370
+ updates [ "$set" ] . each_pair do |key , value |
371
+ if key . split ( '.' ) . last == field
372
+ sets . update ( key => value )
373
+ end
374
+ end
375
+ { "$set" => sets }
376
+ end
353
377
end
354
378
end
Original file line number Diff line number Diff line change @@ -38,6 +38,16 @@ def touch(field = nil)
38
38
# _association.inverse_association.options but inverse_association
39
39
# seems to not always/ever be set here. See MONGOID-5014.
40
40
_parent . touch
41
+
42
+ if field
43
+ # If we are told to also touch a field, perform a separate write
44
+ # for that field. See MONGOID-5136.
45
+ # In theory we should combine the writes, which would require
46
+ # passing the fields to be updated to the parents - MONGOID-5142.
47
+ sets = set_field_atomic_updates ( field )
48
+ selector = atomic_selector
49
+ _root . collection . find ( selector ) . update_one ( positionally ( selector , sets ) , session : _session )
50
+ end
41
51
else
42
52
# If the current document is not embedded, it is composition root
43
53
# and we need to persist the write here.
Original file line number Diff line number Diff line change 131
131
include_examples 'updates the child'
132
132
include_examples 'updates the parent when :touch is true'
133
133
include_examples 'updates the parent when :touch is not set'
134
+
135
+ context 'when also updating an additional field' do
136
+ it 'persists the update to the additional field' do
137
+ entrance
138
+ update_time
139
+ entrance . touch ( :last_used_at )
140
+
141
+ entrance . reload
142
+ building . reload
143
+
144
+ # This is the assertion we want.
145
+ entrance . last_used_at . should == update_time
146
+
147
+ # Check other timestamps for good measure.
148
+ entrance . updated_at . should == update_time
149
+ building . updated_at . should == update_time
150
+ end
151
+ end
134
152
end
135
153
136
154
context "when the document is referenced" do
Original file line number Diff line number Diff line change @@ -15,6 +15,8 @@ class Entrance
15
15
include Mongoid ::Timestamps
16
16
17
17
embedded_in :building
18
+
19
+ field :last_used_at , type : Time
18
20
end
19
21
20
22
class Floor
You can’t perform that action at this time.
0 commit comments