Module: Mongoid::Tree
- Extended by:
- ActiveSupport::Concern
- Defined in:
- lib/mongoid/tree.rb,
lib/mongoid/tree/ordering.rb,
lib/mongoid/tree/traversal.rb,
lib/mongoid/tree/counter_caching.rb
Overview
Mongoid::Tree
This module extends any Mongoid document with tree functionality.
Usage
Simply include the module in any Mongoid document:
class Node
include Mongoid::Document
include Mongoid::Tree
end
Using the tree structure
Each document references many children. You can access them using the #children
method.
node = Node.create
node.children.create
node.children.count # => 1
Every document references one parent (unless it’s a root document).
node = Node.create
node.parent # => nil
node.children.create
node.children.first.parent # => node
Destroying
Mongoid::Tree does not handle destroying of nodes by default. However it provides several strategies that help you to deal with children of deleted documents. You can simply add them as before_destroy
callbacks.
Available strategies are:
-
:nullify_children – Sets the children’s parent_id to null
-
:move_children_to_parent – Moves the children to the current document’s parent
-
:destroy_children – Destroys all children by calling their #destroy method (invokes callbacks)
-
:delete_descendants – Deletes all descendants using a database query (doesn’t invoke callbacks)
Example:
class Node
include Mongoid::Document
include Mongoid::Tree
before_destroy :nullify_children
end
Callbacks
Mongoid::Tree offers callbacks for its rearranging process. This enables you to rebuild certain fields when the document was moved in the tree. Rearranging happens before the document is validated. This gives you a chance to validate your additional changes done in your callbacks. See ActiveModel::Callbacks and ActiveSupport::Callbacks for further details on callbacks.
Example:
class Page
include Mongoid::Document
include Mongoid::Tree
after_rearrange :rebuild_path
field :slug
field :path
private
def rebuild_path
self.path = self.ancestors_and_self.collect(&:slug).join('/')
end
end
Defined Under Namespace
Modules: ClassMethods, CounterCaching, Ordering, Traversal
Class Method Summary collapse
-
.after_rearrange ⇒ undefined
Sets a callback that is called after the document is rearranged.
-
.before_rearrange ⇒ undefined
Sets a callback that is called before the document is rearranged.
Instance Method Summary collapse
-
#ancestor_of?(other) ⇒ Boolean
Is this document an ancestor of the other document?.
-
#ancestors ⇒ Mongoid::Criteria
Returns a chainable criteria for this document’s ancestors.
-
#ancestors_and_self ⇒ Array<Mongoid::Document>
Returns an array of this document’s ancestors and itself.
-
#children ⇒ Mongoid::Criteria
Returns a list of the document’s children.
-
#delete_descendants ⇒ undefined
Deletes all descendants using the database (doesn’t invoke callbacks).
-
#depth ⇒ Fixnum
Returns the depth of this document (number of ancestors).
-
#descendant_of?(other) ⇒ Boolean
Is this document a descendant of the other document?.
-
#descendants ⇒ Mongoid::Criteria
Returns a chainable criteria for this document’s descendants.
-
#descendants_and_self ⇒ Array<Mongoid::Document>
Returns and array of this document and it’s descendants.
-
#destroy_children ⇒ undefined
Destroys all children by calling their #destroy method (does invoke callbacks).
-
#leaf? ⇒ Boolean
Is this document a leaf node (has no children)?.
-
#leaves ⇒ Mongoid::Criteria
Returns all leaves of this document (be careful, currently involves two queries).
-
#move_children_to_parent ⇒ undefined
Moves all children to this document’s parent.
-
#nullify_children ⇒ undefined
Nullifies all children’s parent_id.
-
#parent ⇒ Mongoid::Document
Returns the document’s parent (unless it’s a root document).
-
#parent=(document) ⇒ Object
Sets this documents parent document.
-
#parent_ids ⇒ Array<BSON::ObjectId>
Returns a list of the document’s parent_ids, starting with the root node.
-
#rearrange_children! ⇒ undefined
Forces rearranging of all children after next save.
-
#rearrange_children? ⇒ Boolean
Will the children be rearranged after next save?.
-
#root ⇒ Mongoid::Document
Returns this document’s root node.
-
#root? ⇒ Boolean
Is this document a root node (has no parent)?.
-
#sibling_of?(other) ⇒ Boolean
Is this document a sibling of the other document?.
-
#siblings ⇒ Mongoid::Criteria
Returns this document’s siblings.
-
#siblings_and_self ⇒ Mongoid::Criteria
Returns this document’s siblings and itself.
Class Method Details
.after_rearrange ⇒ undefined
Generated by ActiveSupport
Sets a callback that is called after the document is rearranged
|
# File 'lib/mongoid/tree.rb', line 185
|
.before_rearrange ⇒ undefined
Generated by ActiveSupport
Sets a callback that is called before the document is rearranged
|
# File 'lib/mongoid/tree.rb', line 161
|
Instance Method Details
#ancestor_of?(other) ⇒ Boolean
Is this document an ancestor of the other document?
308 309 310 |
# File 'lib/mongoid/tree.rb', line 308 def ancestor_of?(other) other.parent_ids.include?(self.id) end |
#ancestors ⇒ Mongoid::Criteria
Returns a chainable criteria for this document’s ancestors
290 291 292 |
# File 'lib/mongoid/tree.rb', line 290 def ancestors base_class.where(:_id.in => parent_ids).order(:depth => :asc) end |
#ancestors_and_self ⇒ Array<Mongoid::Document>
Returns an array of this document’s ancestors and itself
298 299 300 |
# File 'lib/mongoid/tree.rb', line 298 def ancestors_and_self ancestors + [self] end |
#children ⇒ Mongoid::Criteria
Generated by Mongoid
Returns a list of the document’s children. It’s a references_many
association.
|
# File 'lib/mongoid/tree.rb', line 209
|
#delete_descendants ⇒ undefined
Deletes all descendants using the database (doesn’t invoke callbacks)
414 415 416 |
# File 'lib/mongoid/tree.rb', line 414 def delete_descendants base_class.delete_all(:conditions => { :parent_ids => self.id }) end |
#depth ⇒ Fixnum
Returns the depth of this document (number of ancestors)
249 250 251 |
# File 'lib/mongoid/tree.rb', line 249 def depth super || parent_ids.count end |
#descendant_of?(other) ⇒ Boolean
Is this document a descendant of the other document?
334 335 336 |
# File 'lib/mongoid/tree.rb', line 334 def descendant_of?(other) self.parent_ids.include?(other.id) end |
#descendants ⇒ Mongoid::Criteria
Returns a chainable criteria for this document’s descendants
316 317 318 |
# File 'lib/mongoid/tree.rb', line 316 def descendants base_class.where(:parent_ids => self.id) end |
#descendants_and_self ⇒ Array<Mongoid::Document>
Returns and array of this document and it’s descendants
324 325 326 |
# File 'lib/mongoid/tree.rb', line 324 def descendants_and_self [self] + descendants end |
#destroy_children ⇒ undefined
Destroys all children by calling their #destroy method (does invoke callbacks)
422 423 424 |
# File 'lib/mongoid/tree.rb', line 422 def destroy_children children.destroy_all end |
#leaf? ⇒ Boolean
Is this document a leaf node (has no children)?
265 266 267 |
# File 'lib/mongoid/tree.rb', line 265 def leaf? children.empty? end |
#leaves ⇒ Mongoid::Criteria
Returns all leaves of this document (be careful, currently involves two queries)
368 369 370 |
# File 'lib/mongoid/tree.rb', line 368 def leaves base_class.where(:_id.nin => base_class.only(:parent_id).collect(&:parent_id)).and(:parent_ids => self.id) end |
#move_children_to_parent ⇒ undefined
Moves all children to this document’s parent
403 404 405 406 407 408 |
# File 'lib/mongoid/tree.rb', line 403 def move_children_to_parent children.each do |c| c.parent = self.parent c.save end end |
#nullify_children ⇒ undefined
Nullifies all children’s parent_id
392 393 394 395 396 397 |
# File 'lib/mongoid/tree.rb', line 392 def nullify_children children.each do |c| c.parent = c.parent_id = nil c.save end end |
#parent ⇒ Mongoid::Document
Generated by Mongoid
Returns the document’s parent (unless it’s a root document). It’s a referenced_in
association.
|
# File 'lib/mongoid/tree.rb', line 217
|
#parent=(document) ⇒ Object
Generated by Mongoid
Sets this documents parent document.
|
# File 'lib/mongoid/tree.rb', line 225
|
#parent_ids ⇒ Array<BSON::ObjectId>
Generated by Mongoid
Returns a list of the document’s parent_ids, starting with the root node.
|
# File 'lib/mongoid/tree.rb', line 233
|
#rearrange_children! ⇒ undefined
Forces rearranging of all children after next save
376 377 378 |
# File 'lib/mongoid/tree.rb', line 376 def rearrange_children! @rearrange_children = true end |
#rearrange_children? ⇒ Boolean
Will the children be rearranged after next save?
384 385 386 |
# File 'lib/mongoid/tree.rb', line 384 def rearrange_children? !!@rearrange_children end |
#root ⇒ Mongoid::Document
Returns this document’s root node. Returns ‘self` if the current document is a root node
278 279 280 281 282 283 284 |
# File 'lib/mongoid/tree.rb', line 278 def root if parent_ids.present? base_class.find(parent_ids.first) else self.root? ? self : self.parent.root end end |
#root? ⇒ Boolean
Is this document a root node (has no parent)?
257 258 259 |
# File 'lib/mongoid/tree.rb', line 257 def root? parent_id.nil? end |
#sibling_of?(other) ⇒ Boolean
Is this document a sibling of the other document?
360 361 362 |
# File 'lib/mongoid/tree.rb', line 360 def sibling_of?(other) self.parent_id == other.parent_id end |
#siblings ⇒ Mongoid::Criteria
Returns this document’s siblings
342 343 344 |
# File 'lib/mongoid/tree.rb', line 342 def siblings siblings_and_self.excludes(:id => self.id) end |
#siblings_and_self ⇒ Mongoid::Criteria
Returns this document’s siblings and itself
350 351 352 |
# File 'lib/mongoid/tree.rb', line 350 def siblings_and_self base_class.where(:parent_id => self.parent_id) end |