@@ -47,18 +47,22 @@ def shard_key_fields
47
47
self . class . shard_key_fields
48
48
end
49
49
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.
52
58
#
53
59
# @return [ Hash ] The shard key selector.
54
60
#
55
61
# @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 )
60
65
end
61
- selector
62
66
end
63
67
64
68
# Returns the selector that would match the existing version of this
@@ -72,11 +76,31 @@ def shard_key_selector
72
76
#
73
77
# @api private
74
78
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 )
78
103
end
79
- selector
80
104
end
81
105
82
106
module ClassMethods
0 commit comments