Module: Mongoid::Traversable
Overview
Mixin module included in Mongoid::Document to provide behavior around traversing the document graph.
Defined Under Namespace
Modules: ClassMethods, DiscriminatorAssignment, DiscriminatorRetrieval
Class Method Summary collapse
Instance Method Summary collapse
-
#_children(reset: false) ⇒ Array<Document>
private
Get all child
Documents
to thisDocument
. -
#_descendants(reset: false) ⇒ Array<Document>
private
Get all descendant
Documents
of thisDocument
recursively. -
#_parent ⇒ Mongoid::Document | nil
private
Retrieves the parent document of this document.
-
#_parent=(document) ⇒ Object
private
Sets the parent document of this document.
-
#_reset_memoized_descendants! ⇒ nil
private
Resets the memoized descendants on the object.
-
#_root ⇒ Document
Return the root document in the object graph.
-
#_root? ⇒ true | false
Is this document the root document of the hierarchy?.
-
#collect_children ⇒ Array<Document>
private
Collect all the children of this document.
-
#collect_descendants ⇒ Array<Document>
private
Collect all the descendants of this document.
-
#flag_descendants_persisted ⇒ Array<Document>
Marks all descendants as being persisted.
-
#hereditary? ⇒ true | false
Determines if the document is a subclass of another document.
-
#parentize(document) ⇒ Document
Sets up a child/parent association.
-
#remove_child(child) ⇒ Object
Remove a child document from this parent.
-
#reset_persisted_descendants ⇒ Array<Document>
After descendants are persisted we can call this to move all their changes and flag them as persisted in one call.
Class Method Details
.__redefine(owner, name, value) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/mongoid/traversable.rb', line 17 def __redefine(owner, name, value) if owner.singleton_class? owner.redefine_method(name) { value } owner.send(:public, name) end owner.redefine_singleton_method(name) { value } owner.singleton_class.send(:public, name) owner.redefine_singleton_method("#{name}=") do |new_value| if owner.equal?(self) value = new_value else ::Mongoid::Traversable.redefine(self, name, new_value) end end owner.singleton_class.send(:public, "#{name}=") end |
Instance Method Details
#_children(reset: false) ⇒ Array<Document>
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Get all child Documents
to this Document
238 239 240 241 242 243 244 245 246 247 248 249 |
# File 'lib/mongoid/traversable.rb', line 238 def _children(reset: false) # See discussion above for the `_parent` method, as to why the variable # here needs to have two underscores. # # rubocop:disable Naming/MemoizedInstanceVariableName if reset @__children = nil else @__children ||= collect_children end # rubocop:enable Naming/MemoizedInstanceVariableName end |
#_descendants(reset: false) ⇒ Array<Document>
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Get all descendant Documents
of this Document
recursively. This is used when calling update persistence operations from the root document, where changes in the entire tree need to be determined. Note that persistence from the embedded documents will always be preferred, since they are optimized calls… This operation can get expensive in domains with large hierarchies.
261 262 263 264 265 266 267 268 269 270 271 272 |
# File 'lib/mongoid/traversable.rb', line 261 def _descendants(reset: false) # See discussion above for the `_parent` method, as to why the variable # here needs to have two underscores. # # rubocop:disable Naming/MemoizedInstanceVariableName if reset @__descendants = nil else @__descendants ||= collect_descendants end # rubocop:enable Naming/MemoizedInstanceVariableName end |
#_parent ⇒ Mongoid::Document | nil
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Retrieves the parent document of this document.
109 110 111 |
# File 'lib/mongoid/traversable.rb', line 109 def _parent @__parent || nil end |
#_parent=(document) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Sets the parent document of this document.
121 122 123 |
# File 'lib/mongoid/traversable.rb', line 121 def _parent=(document) @__parent = document end |
#_reset_memoized_descendants! ⇒ nil
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Resets the memoized descendants on the object. Called internally when an embedded array changes size.
388 389 390 391 392 |
# File 'lib/mongoid/traversable.rb', line 388 def _reset_memoized_descendants! _parent&._reset_memoized_descendants! _children reset: true _descendants reset: true end |
#_root ⇒ Document
Return the root document in the object graph. If the current document is the root object in the graph it will return self.
401 402 403 404 405 |
# File 'lib/mongoid/traversable.rb', line 401 def _root object = self object = object._parent while object._parent object end |
#_root? ⇒ true | false
Is this document the root document of the hierarchy?
413 414 415 |
# File 'lib/mongoid/traversable.rb', line 413 def _root? _parent ? false : true end |
#collect_children ⇒ Array<Document>
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Collect all the children of this document.
279 280 281 282 283 284 285 286 287 288 |
# File 'lib/mongoid/traversable.rb', line 279 def collect_children [].tap do |children| .each_pair do |name, _association| without_autobuild do child = send(name) children.concat(Array.wrap(child)) if child end end end end |
#collect_descendants ⇒ Array<Document>
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Collect all the descendants of this document.
295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 |
# File 'lib/mongoid/traversable.rb', line 295 def collect_descendants children = [] = _children = {} until .empty? = = [] .each do |child| next if [child] # Don't mark expanded if _id is nil, since documents are compared by # their _ids, multiple embedded documents with nil ids will compare # equally, and some documents will not be expanded. [child] = true if child._id children << child += child._children end end children end |
#flag_descendants_persisted ⇒ Array<Document>
Marks all descendants as being persisted.
321 322 323 324 325 |
# File 'lib/mongoid/traversable.rb', line 321 def flag_descendants_persisted _descendants.each do |child| child.new_record = false end end |
#hereditary? ⇒ true | false
Determines if the document is a subclass of another document.
333 334 335 |
# File 'lib/mongoid/traversable.rb', line 333 def hereditary? self.class.hereditary? end |
#parentize(document) ⇒ Document
Sets up a child/parent association. This is used for newly created objects so they can be properly added to the graph.
346 347 348 |
# File 'lib/mongoid/traversable.rb', line 346 def parentize(document) self._parent = document end |
#remove_child(child) ⇒ Object
Remove a child document from this parent. If an embeds one then set to nil, otherwise remove from the embeds many.
This is called from the RemoveEmbedded
persistence command.
359 360 361 362 363 364 365 366 367 368 |
# File 'lib/mongoid/traversable.rb', line 359 def remove_child(child) name = child.association_name if child. attributes.delete(child._association.store_as) remove_ivar(name) else relation = send(name) relation._remove(child) end end |
#reset_persisted_descendants ⇒ Array<Document>
After descendants are persisted we can call this to move all their changes and flag them as persisted in one call.
374 375 376 377 378 379 380 |
# File 'lib/mongoid/traversable.rb', line 374 def reset_persisted_descendants _descendants.each do |child| child.move_changes child.new_record = false end _reset_memoized_descendants! end |