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)
385385 updates = atomic_updates
386386 return { } unless atomic_updates . key? ( "$set" )
387387 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
388394 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
391398 end
392399 { "$set" => touches }
393400 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
394418 end
395419end
Original file line number Diff line number Diff line change @@ -41,6 +41,16 @@ def touch(field = nil)
4141 # _association.inverse_association.options but inverse_association
4242 # seems to not always/ever be set here. See MONGOID-5014.
4343 _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.
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
4454 else
4555 # If the current document is not embedded, it is composition root
4656 # and we need to persist the write here.
Original file line number Diff line number Diff line change 132132 include_examples 'updates the child'
133133 include_examples 'updates the parent when :touch is true'
134134 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
135153 end
136154
137155 context "when the document is referenced" do
Original file line number Diff line number Diff line change @@ -16,6 +16,8 @@ class Entrance
1616 include Mongoid ::Timestamps
1717
1818 embedded_in :building
19+
20+ field :last_used_at , type : Time
1921 end
2022
2123 class Floor
You can’t perform that action at this time.
0 commit comments