@@ -115,49 +115,82 @@ def self.get_discriminator_mapping(value)
115115 end
116116 end
117117
118- # Get all child +Documents+ to this +Document+, going n levels deep if
119- # necessary. This is used when calling update persistence operations from
118+ # Get all child +Documents+ to this +Document+
119+ #
120+ # @return [ Array<Document> ] All child documents in the hierarchy.
121+ #
122+ # @api private
123+ def _children
124+ @__children ||= collect_children
125+ end
126+
127+ # Get all descendant +Documents+ of this +Document+ recursively.
128+ # This is used when calling update persistence operations from
120129 # the root document, where changes in the entire tree need to be
121130 # determined. Note that persistence from the embedded documents will
122131 # always be preferred, since they are optimized calls... This operation
123132 # can get expensive in domains with large hierarchies.
124133 #
125- # @example Get all the document's children.
126- # person._children
134+ # @return [ Array<Document> ] All descendant documents in the hierarchy.
127135 #
128- # @return [ Array<Document> ] All child documents in the hierarchy.
129- def _children
130- @__children ||= collect_children
136+ # @api private
137+ def _descendants
138+ @__descendants ||= collect_descendants
131139 end
132140
133141 # Collect all the children of this document.
134142 #
135- # @example Collect all the children.
136- # document.collect_children
137- #
138143 # @return [ Array<Document> ] The children.
144+ #
145+ # @api private
139146 def collect_children
140147 children = [ ]
141148 embedded_relations . each_pair do |name , association |
142149 without_autobuild do
143150 child = send ( name )
144- Array . wrap ( child ) . each do |doc |
145- children . push ( doc )
146- children . concat ( doc . _children )
147- end if child
151+ if child
152+ children += Array . wrap ( child )
153+ end
148154 end
149155 end
150156 children
151157 end
152158
153- # Marks all children as being persisted .
159+ # Collect all the descendants of this document .
154160 #
155- # @example Flag all the children.
156- # document.flag_children_persisted
161+ # @return [ Array<Document> ] The descendants.
162+ #
163+ # @api private
164+ def collect_descendants
165+ children = [ ]
166+ to_expand = [ ]
167+ expanded = { }
168+ embedded_relations . each_pair do |name , association |
169+ without_autobuild do
170+ child = send ( name )
171+ if child
172+ to_expand += Array . wrap ( child )
173+ end
174+ end
175+ end
176+ until to_expand . empty?
177+ expanding = to_expand
178+ to_expand = [ ]
179+ expanding . each do |child |
180+ next if expanded [ child ]
181+ expanded [ child ] = true
182+ children << child
183+ to_expand += child . _children
184+ end
185+ end
186+ children
187+ end
188+
189+ # Marks all descendants as being persisted.
157190 #
158- # @return [ Array<Document> ] The flagged children .
159- def flag_children_persisted
160- _children . each do |child |
191+ # @return [ Array<Document> ] The flagged descendants .
192+ def flag_descendants_persisted
193+ _descendants . each do |child |
161194 child . new_record = false
162195 end
163196 end
@@ -204,33 +237,28 @@ def remove_child(child)
204237 end
205238 end
206239
207- # After children are persisted we can call this to move all their changes
208- # and flag them as persisted in one call.
240+ # After descendants are persisted we can call this to move all their
241+ # changes and flag them as persisted in one call.
209242 #
210- # @example Reset the children.
211- # document.reset_persisted_children
212- #
213- # @return [ Array<Document> ] The children.
214- def reset_persisted_children
215- _children . each do |child |
243+ # @return [ Array<Document> ] The descendants.
244+ def reset_persisted_descendants
245+ _descendants . each do |child |
216246 child . move_changes
217247 child . new_record = false
218248 end
219- _reset_memoized_children !
249+ _reset_memoized_descendants !
220250 end
221251
222- # Resets the memoized children on the object. Called internally when an
252+ # Resets the memoized descendants on the object. Called internally when an
223253 # embedded array changes size.
224254 #
225- # @api semiprivate
226- #
227- # @example Reset the memoized children.
228- # document._reset_memoized_children!
229- #
230255 # @return [ nil ] nil.
231- def _reset_memoized_children!
232- _parent . _reset_memoized_children! if _parent
256+ #
257+ # @api private
258+ def _reset_memoized_descendants!
259+ _parent . _reset_memoized_descendants! if _parent
233260 @__children = nil
261+ @__descendants = nil
234262 end
235263
236264 # Return the root document in the object graph. If the current document
0 commit comments