Module: Mongoid::Traversable
Relationships & Source Files | |
Namespace Children | |
Modules:
| |
Extension / Inclusion / Inheritance Descendants | |
Included In:
| |
Super Chains via Extension / Inclusion / Inheritance | |
Class Chain:
self,
ActiveSupport::Concern
|
|
Defined in: | lib/mongoid/traversable.rb |
Overview
Mixin module included in Document
to provide behavior around traversing the document graph.
Class Method Summary
- .__redefine(owner, name, value) Internal use only Internal use only
Instance Attribute Summary
-
#_parent ⇒ Mongoid::Document | nil
rw
Internal use only
Internal use only
Retrieves the parent document of this document.
-
#_parent=(document)
rw
Internal use only
Internal use only
Sets the parent document of this document.
-
#_root ⇒ Document
readonly
Return the root document in the object graph.
-
#_root? ⇒ true | false
readonly
Is this document the root document of the hierarchy?
-
#hereditary? ⇒ true | false
readonly
Determines if the document is a subclass of another document.
Instance Method Summary
-
#_children(reset: false) ⇒ Array<Document>
Internal use only
Internal use only
Get all child
Documents
to thisDocument
-
#_descendants(reset: false) ⇒ Array<Document>
Internal use only
Internal use only
Get all descendant
Documents
of thisDocument
recursively. -
#_reset_memoized_descendants! ⇒ nil
Internal use only
Internal use only
Resets the memoized descendants on the object.
-
#collect_children ⇒ Array<Document>
Internal use only
Internal use only
Collect all the children of this document.
-
#collect_descendants ⇒ Array<Document>
Internal use only
Internal use only
Collect all the descendants of this document.
-
#flag_descendants_persisted ⇒ Array<Document>
Marks all descendants as being persisted.
-
#parentize(document) ⇒ Document
Sets up a child/parent association.
-
#remove_child(child)
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.
DSL Calls
included
[ GitHub ]180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
# File 'lib/mongoid/traversable.rb', line 180
included do class_attribute :discriminator_key, instance_accessor: false class << self # The class attribute declaration above creates a default getter which we override with our custom method. remove_method :discriminator_key delegate :discriminator_key, to: ::Mongoid prepend DiscriminatorAssignment include DiscriminatorRetrieval # @api private # # @return [ Hash<String, Class> ] The current mapping of discriminator_values to classes attr_accessor :discriminator_mapping end # Add a discriminator mapping to the parent class. This mapping is used when # receiving a document to identify its class. # # @param [ String ] value The discriminator_value that was just set # @param [ Class ] The class the discriminator_value was set on # # @api private def self.add_discriminator_mapping(value, klass = self) self.discriminator_mapping ||= {} self.discriminator_mapping[value] = klass superclass.add_discriminator_mapping(value, klass) if hereditary? end # Get the discriminator mapping from the parent class. This method returns nil if there # is no mapping for the given value. # # @param [ String ] value The discriminator_value to retrieve # # @return [ Class | nil ] klass The class corresponding to the given discriminator_value. If # the value is not in the mapping, this method returns nil. # # @api private def self.get_discriminator_mapping(value) self.discriminator_mapping[value] if self.discriminator_mapping end end
Class Method Details
.__redefine(owner, name, value)
# 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 Attribute Details
#_parent ⇒ Mongoid::Document | nil
(rw)
Retrieves the parent document of this document.
# File 'lib/mongoid/traversable.rb', line 97
def _parent @__parent || nil end
#_parent=(document) (rw)
Sets the parent document of this document.
# File 'lib/mongoid/traversable.rb', line 109
def _parent=(document) @__parent = document end
#_root ⇒ Document (readonly)
Return the root document in the object graph. If the current document is the root object in the graph it will return self.
#_root? ⇒ true
| false
(readonly)
Is this document the root document of the hierarchy?
# File 'lib/mongoid/traversable.rb', line 402
def _root? _parent ? false : true end
#hereditary? ⇒ true
| false
(readonly)
Determines if the document is a subclass of another document.
# File 'lib/mongoid/traversable.rb', line 322
def hereditary? self.class.hereditary? end
Instance Method Details
#_children(reset: false) ⇒ Array<Document>
Get all child Documents
to this Document
# File 'lib/mongoid/traversable.rb', line 227
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>
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.
# File 'lib/mongoid/traversable.rb', line 250
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
#_reset_memoized_descendants! ⇒ nil
Resets the memoized descendants on the object. Called internally when an embedded array changes size.
# File 'lib/mongoid/traversable.rb', line 377
def _reset_memoized_descendants! _parent&._reset_memoized_descendants! _children reset: true _descendants reset: true end
#collect_children ⇒ Array<Document>
Collect all the children of this document.
# File 'lib/mongoid/traversable.rb', line 268
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>
Collect all the descendants of this document.
# File 'lib/mongoid/traversable.rb', line 284
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.
# File 'lib/mongoid/traversable.rb', line 310
def flag_descendants_persisted _descendants.each do |child| child.new_record = false end 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.
# File 'lib/mongoid/traversable.rb', line 335
def parentize(document) self._parent = document end
#remove_child(child)
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.
# File 'lib/mongoid/traversable.rb', line 348
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.
# File 'lib/mongoid/traversable.rb', line 363
def reset_persisted_descendants _descendants.each do |child| child.move_changes child.new_record = false end _reset_memoized_descendants! end