module Mongoid::Tree::Ordering
Mongoid::Tree::Ordering
¶ ↑
Mongoid::Tree
doesn’t order the tree by default. To enable ordering of children include both Mongoid::Tree
and Mongoid::Tree::Ordering
into your document.
Utility methods¶ ↑
This module adds methods to get related siblings depending on their position:
node.lower_siblings node.higher_siblings node.first_sibling_in_list node.last_sibling_in_list
There are several methods to move nodes around in the list:
node.move_up node.move_down node.move_to_top node.move_to_bottom node.move_above(other) node.move_below(other)
Additionally there are some methods to check aspects of the document in the list of children:
node.at_top? node.at_bottom?
Public Instance Methods
Returns a chainable criteria for this document’s ancestors
@return [Mongoid::Criteria] Mongoid
criteria to retrieve the document’s ancestors
# File lib/mongoid/tree/ordering.rb, line 49 def ancestors base_class.unscoped { super } end
Is this the lowest sibling?
@return [Boolean] Whether the document is the lowest sibling
# File lib/mongoid/tree/ordering.rb, line 109 def at_bottom? lower_siblings.empty? end
Is this the highest sibling?
@return [Boolean] Whether the document is the highest sibling
# File lib/mongoid/tree/ordering.rb, line 101 def at_top? higher_siblings.empty? end
Returns the highest sibling (could be self)
@return [Mongoid::Document] The highest sibling
# File lib/mongoid/tree/ordering.rb, line 93 def first_sibling_in_list siblings_and_self.first end
Returns siblings above the current document. Siblings with a position lower than this document’s position.
@return [Mongoid::Criteria] Mongoid
criteria to retrieve the document’s higher siblings
# File lib/mongoid/tree/ordering.rb, line 67 def higher_siblings self.siblings.where(:position.lt => self.position) end
Returns the lowest sibling (could be self)
@return [Mongoid::Document] The lowest sibling
# File lib/mongoid/tree/ordering.rb, line 85 def last_sibling_in_list siblings_and_self.last end
Returns siblings below the current document. Siblings with a position greater than this document’s position.
@return [Mongoid::Criteria] Mongoid
criteria to retrieve the document’s lower siblings
# File lib/mongoid/tree/ordering.rb, line 58 def lower_siblings self.siblings.where(:position.gt => self.position) end
Move this node above the specified node
This method changes the node’s parent if nescessary.
@param [Mongoid::Tree] other document to move this document above
@return [void]
# File lib/mongoid/tree/ordering.rb, line 155 def move_above(other) ensure_to_be_sibling_of(other) if position > other.position new_position = other.position self.siblings_between(other).inc(position: 1) other.inc(position: 1) else new_position = other.position - 1 self.siblings_between(other).inc(position: -1) end self.position = new_position save! end
Move this node below the specified node
This method changes the node’s parent if nescessary.
@param [Mongoid::Tree] other document to move this document below
@return [void]
# File lib/mongoid/tree/ordering.rb, line 179 def move_below(other) ensure_to_be_sibling_of(other) if position > other.position new_position = other.position + 1 self.siblings_between(other).inc(position: 1) else new_position = other.position self.siblings_between(other).inc(position: -1) other.inc(position: -1) end self.position = new_position save! end
Move this node one position down
@return [void]
# File lib/mongoid/tree/ordering.rb, line 143 def move_down switch_with_sibling_at_offset(1) unless at_bottom? end
Move this node below all its siblings
@return [void]
# File lib/mongoid/tree/ordering.rb, line 126 def move_to_bottom return true if at_bottom? move_below(last_sibling_in_list) end
Move this node above all its siblings
@return [void]
# File lib/mongoid/tree/ordering.rb, line 117 def move_to_top return true if at_top? move_above(first_sibling_in_list) end
Move this node one position up
@return [void]
# File lib/mongoid/tree/ordering.rb, line 135 def move_up switch_with_sibling_at_offset(-1) unless at_top? end
Returns siblings between the current document and the other document Siblings with a position between this document’s position and the other document’s position.
@return [Mongoid::Criteria] Mongoid
criteria to retrieve the documents between this and the other document
# File lib/mongoid/tree/ordering.rb, line 76 def siblings_between(other) range = [self.position, other.position].sort self.siblings.where(:position.gt => range.first, :position.lt => range.last) end
Private Instance Methods
# File lib/mongoid/tree/ordering.rb, line 223 def assign_default_position self.position = if self.siblings.where(:position.ne => nil).any? self.last_sibling_in_list.position + 1 else 0 end end
# File lib/mongoid/tree/ordering.rb, line 231 def assign_default_position? self.position.nil? || self.parent_id_changed? end
# File lib/mongoid/tree/ordering.rb, line 202 def ensure_to_be_sibling_of(other) return if sibling_of?(other) self.parent_id = other.parent_id save! end
# File lib/mongoid/tree/ordering.rb, line 208 def move_lower_siblings_up lower_siblings.inc(position: -1) end
# File lib/mongoid/tree/ordering.rb, line 212 def reposition_former_siblings former_siblings = base_class.where(:parent_id => attribute_was('parent_id')). and(:position.gt => (attribute_was('position') || 0)). excludes(:id => self.id) former_siblings.inc(position: -1) end
# File lib/mongoid/tree/ordering.rb, line 219 def sibling_reposition_required? parent_id_changed? && persisted? end
# File lib/mongoid/tree/ordering.rb, line 197 def switch_with_sibling_at_offset(offset) siblings.where(position: self.position + offset).first.inc(position: -offset) inc(position: offset) end