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)
344344 updates = atomic_updates
345345 return { } unless atomic_updates . key? ( "$set" )
346346 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
347353 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
350357 end
351358 { "$set" => touches }
352359 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
353377 end
354378end
Original file line number Diff line number Diff line change @@ -38,6 +38,16 @@ def touch(field = nil)
3838 # _association.inverse_association.options but inverse_association
3939 # seems to not always/ever be set here. See MONGOID-5014.
4040 _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
4151 else
4252 # If the current document is not embedded, it is composition root
4353 # and we need to persist the write here.
Original file line number Diff line number Diff line change 131131 include_examples 'updates the child'
132132 include_examples 'updates the parent when :touch is true'
133133 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
134152 end
135153
136154 context "when the document is referenced" do
Original file line number Diff line number Diff line change @@ -15,6 +15,8 @@ class Entrance
1515 include Mongoid ::Timestamps
1616
1717 embedded_in :building
18+
19+ field :last_used_at , type : Time
1820 end
1921
2022 class Floor
You can’t perform that action at this time.
0 commit comments