@@ -47,18 +47,22 @@ def shard_key_fields
4747 self . class . shard_key_fields
4848 end
4949
50- # Returns the selector that would match the current version of this
51- # document.
50+ # Returns the selector that would match the defined shard keys. If
51+ # `prefer_persisted` is false (the default), it uses the current values
52+ # of the specified shard keys, otherwise, it will try to use whatever value
53+ # was most recently persisted.
54+ #
55+ # @param [ true | false ] prefer_persisted Whether to use the current
56+ # value of the shard key fields, or to use their most recently persisted
57+ # values.
5258 #
5359 # @return [ Hash ] The shard key selector.
5460 #
5561 # @api private
56- def shard_key_selector
57- selector = { }
58- shard_key_fields . each do |field |
59- selector [ field . to_s ] = send ( field )
62+ def shard_key_selector ( prefer_persisted : false )
63+ shard_key_fields . each_with_object ( { } ) do |field , selector |
64+ selector [ field . to_s ] = shard_key_field_value ( field . to_s , prefer_persisted : prefer_persisted )
6065 end
61- selector
6266 end
6367
6468 # Returns the selector that would match the existing version of this
@@ -72,11 +76,31 @@ def shard_key_selector
7276 #
7377 # @api private
7478 def shard_key_selector_in_db
75- selector = { }
76- shard_key_fields . each do |field |
77- selector [ field . to_s ] = new_record? ? send ( field ) : attribute_was ( field )
79+ shard_key_selector ( prefer_persisted : true )
80+ end
81+
82+ # Returns the value for the named shard key. If the field identifies
83+ # an embedded document, the key will be parsed and recursively evaluated.
84+ # If `prefer_persisted` is true, the value last persisted to the database
85+ # will be returned, regardless of what the current value of the attribute
86+ # may be.
87+ #
88+ # @param [String] field The name of the field to evaluate
89+ # @param [ true|false ] prefer_persisted Whether or not to prefer the
90+ # persisted value over the current value.
91+ #
92+ # @return [ Object ] The value of the named field.
93+ #
94+ # @api private
95+ def shard_key_field_value ( field , prefer_persisted :)
96+ if field . include? ( "." )
97+ relation , remaining = field . split ( "." , 2 )
98+ send ( relation ) &.shard_key_field_value ( remaining , prefer_persisted : prefer_persisted )
99+ elsif prefer_persisted && !new_record?
100+ attribute_was ( field )
101+ else
102+ send ( field )
78103 end
79- selector
80104 end
81105
82106 module ClassMethods
0 commit comments