Module: Mongoid::Tree
- Extended by:
- ActiveSupport::Concern
- Defined in:
- lib/mongoid/tree.rb,
lib/mongoid/tree/ordering.rb,
lib/mongoid/tree/traversal.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, 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 184
|
.before_rearrange ⇒ undefined
Generated by ActiveSupport
Sets a callback that is called before the document is rearranged
|
# File 'lib/mongoid/tree.rb', line 160
|
Instance Method Details
#ancestor_of?(other) ⇒ Boolean
Is this document an ancestor of the other document?
307 308 309 |
# File 'lib/mongoid/tree.rb', line 307 def ancestor_of?(other) other.parent_ids.include?(self.id) end |
#ancestors ⇒ Mongoid::Criteria
Returns a chainable criteria for this document's ancestors
289 290 291 |
# File 'lib/mongoid/tree.rb', line 289 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
297 298 299 |
# File 'lib/mongoid/tree.rb', line 297 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 208
|
#delete_descendants ⇒ undefined
Deletes all descendants using the database (doesn't invoke callbacks)
413 414 415 |
# File 'lib/mongoid/tree.rb', line 413 def delete_descendants base_class.delete_all(:conditions => { :parent_ids => self.id }) end |
#depth ⇒ Fixnum
Returns the depth of this document (number of ancestors)
248 249 250 |
# File 'lib/mongoid/tree.rb', line 248 def depth super || parent_ids.count end |
#descendant_of?(other) ⇒ Boolean
Is this document a descendant of the other document?
333 334 335 |
# File 'lib/mongoid/tree.rb', line 333 def descendant_of?(other) self.parent_ids.include?(other.id) end |
#descendants ⇒ Mongoid::Criteria
Returns a chainable criteria for this document's descendants
315 316 317 |
# File 'lib/mongoid/tree.rb', line 315 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
323 324 325 |
# File 'lib/mongoid/tree.rb', line 323 def descendants_and_self [self] + descendants end |
#destroy_children ⇒ undefined
Destroys all children by calling their #destroy method (does invoke callbacks)
421 422 423 |
# File 'lib/mongoid/tree.rb', line 421 def destroy_children children.destroy_all end |
#leaf? ⇒ Boolean
Is this document a leaf node (has no children)?
264 265 266 |
# File 'lib/mongoid/tree.rb', line 264 def leaf? children.empty? end |
#leaves ⇒ Mongoid::Criteria
Returns all leaves of this document (be careful, currently involves two queries)
367 368 369 |
# File 'lib/mongoid/tree.rb', line 367 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
402 403 404 405 406 407 |
# File 'lib/mongoid/tree.rb', line 402 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
391 392 393 394 395 396 |
# File 'lib/mongoid/tree.rb', line 391 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 216
|
#parent=(document) ⇒ Object
Generated by Mongoid
Sets this documents parent document.
|
# File 'lib/mongoid/tree.rb', line 224
|
#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 232
|
#rearrange_children! ⇒ undefined
Forces rearranging of all children after next save
375 376 377 |
# File 'lib/mongoid/tree.rb', line 375 def rearrange_children! @rearrange_children = true end |
#rearrange_children? ⇒ Boolean
Will the children be rearranged after next save?
383 384 385 |
# File 'lib/mongoid/tree.rb', line 383 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
277 278 279 280 281 282 283 |
# File 'lib/mongoid/tree.rb', line 277 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)?
256 257 258 |
# File 'lib/mongoid/tree.rb', line 256 def root? parent_id.nil? end |
#sibling_of?(other) ⇒ Boolean
Is this document a sibling of the other document?
359 360 361 |
# File 'lib/mongoid/tree.rb', line 359 def sibling_of?(other) self.parent_id == other.parent_id end |
#siblings ⇒ Mongoid::Criteria
Returns this document's siblings
341 342 343 |
# File 'lib/mongoid/tree.rb', line 341 def siblings siblings_and_self.excludes(:id => self.id) end |
#siblings_and_self ⇒ Mongoid::Criteria
Returns this document's siblings and itself
349 350 351 |
# File 'lib/mongoid/tree.rb', line 349 def siblings_and_self base_class.where(:parent_id => self.parent_id) end |