Module: ActsAsOrderedTree::InstanceMethods
- Includes:
- TenaciousTransaction
- Defined in:
- lib/acts_as_ordered_tree/instance_methods.rb
Constant Summary
Constants included from TenaciousTransaction
TenaciousTransaction::DEADLOCK_MESSAGES, TenaciousTransaction::RETRY_COUNT
Instance Method Summary collapse
-
#ancestors ⇒ Object
Returns the array of all parents starting from root.
- #branch? ⇒ Boolean
-
#child? ⇒ Boolean
Returns true is this is a child node.
-
#descendants ⇒ Object
Returns a set of all of its children and nested children.
-
#first? ⇒ Boolean
Return
true
if this object is the first in the list. -
#insert_at(position = 1) ⇒ Object
Insert the item at the given position (defaults to the top position of 1).
- #is_ancestor_of?(other) ⇒ Boolean
- #is_descendant_of?(other) ⇒ Boolean
- #is_or_is_ancestor_of?(other) ⇒ Boolean
- #is_or_is_descendant_of?(other) ⇒ Boolean
-
#last? ⇒ Boolean
Return
true
if this object is the last in the list. -
#leaf? ⇒ Boolean
Returns true if this is the end of a branch.
-
#left_sibling ⇒ Object
(also: #higher_item)
Returns a left (upper) sibling of the node.
- #level ⇒ Object
-
#move_left ⇒ Object
(also: #move_higher)
Shorthand method for finding the left sibling and moving to the left of it.
-
#move_possible?(target) ⇒ Boolean
Returns
true
it is possible to move node to left/right/child oftarget
. -
#move_right ⇒ Object
(also: #move_lower)
Shorthand method for finding the right sibling and moving to the right of it.
-
#move_to_child_of(node) ⇒ Object
Move the node to the child of another node.
-
#move_to_child_with_index(node, index) ⇒ Object
Move the node to the child of another node with specify index.
-
#move_to_left_of(node) ⇒ Object
(also: #move_to_above_of)
Move the node to the left of another node.
-
#move_to_right_of(node) ⇒ Object
(also: #move_to_bottom_of)
Move the node to the left of another node.
-
#move_to_root ⇒ Object
Move the node to root nodes.
-
#right_sibling ⇒ Object
(also: #lower_item)
Returns a right (lower) sibling of the node.
-
#root ⇒ Object
Returns root (not really fast operation).
-
#root? ⇒ Boolean
Returns true if this is a root node.
-
#same_scope?(other) ⇒ Boolean
Check if other model is in the same scope.
-
#self_and_ancestors ⇒ Object
Returns the array of all parents and self starting from root.
-
#self_and_descendants ⇒ Object
Returns a set of itself and all of its nested children.
-
#self_and_siblings ⇒ Object
Returns the array of all children of the parent, including self.
-
#siblings ⇒ Object
Returns the array of all children of the parent, except self.
Methods included from TenaciousTransaction
Instance Method Details
#ancestors ⇒ Object
Returns the array of all parents starting from root
60 61 62 63 64 65 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 60 def ancestors records = self_and_ancestors - [self] scope = self_and_ancestors.where(arel[:id].not_eq(id)) scope.records(records) end |
#branch? ⇒ Boolean
24 25 26 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 24 def branch? !leaf? end |
#child? ⇒ Boolean
Returns true is this is a child node
29 30 31 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 29 def child? !root? end |
#descendants ⇒ Object
Returns a set of all of its children and nested children. A little bit tricky. use RDBMS with recursive queries support (PostgreSQL)
94 95 96 97 98 99 100 101 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 94 def descendants records = fetch_self_and_descendants - [self] ActsAsOrderedTree::Relation::Preloaded.new(self.class). where(:id => records.map(&:id).compact). extending(Arrangeable). records(records) end |
#first? ⇒ Boolean
Return true
if this object is the first in the list.
130 131 132 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 130 def first? self[position_column] <= 1 end |
#insert_at(position = 1) ⇒ Object
Insert the item at the given position (defaults to the top position of 1). acts_as_list
compatability
159 160 161 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 159 def insert_at(position = 1) move_to_child_with_index(parent, position - 1) end |
#is_ancestor_of?(other) ⇒ Boolean
121 122 123 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 121 def is_ancestor_of?(other) other.is_descendant_of? self end |
#is_descendant_of?(other) ⇒ Boolean
113 114 115 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 113 def is_descendant_of?(other) ancestors.include? other end |
#is_or_is_ancestor_of?(other) ⇒ Boolean
125 126 127 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 125 def is_or_is_ancestor_of?(other) other.is_or_is_descendant_of? self end |
#is_or_is_descendant_of?(other) ⇒ Boolean
117 118 119 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 117 def is_or_is_descendant_of?(other) self == other || is_descendant_of?(other) end |
#last? ⇒ Boolean
Return true
if this object is the last in the list.
135 136 137 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 135 def last? !right_sibling end |
#leaf? ⇒ Boolean
Returns true if this is the end of a branch.
16 17 18 19 20 21 22 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 16 def leaf? persisted? && if children_counter_cache_column self[children_counter_cache_column] == 0 else !children.reorder(nil).exists? end end |
#left_sibling ⇒ Object Also known as: higher_item
Returns a left (upper) sibling of the node
140 141 142 143 144 145 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 140 def left_sibling siblings. where( arel[position_column].lt(self[position_column]) ). reorder( arel[position_column].desc ). first end |
#level ⇒ Object
77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 77 def level if depth_column # cached result becomes invalid when parent is changed if new_record? || changed_attributes.include?(parent_column.to_s) || self[depth_column].blank? self[depth_column] = compute_level else self[depth_column] end else compute_level end end |
#move_left ⇒ Object Also known as: move_higher
Shorthand method for finding the left sibling and moving to the left of it.
164 165 166 167 168 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 164 def move_left tenacious_transaction do move_to_left_of left_sibling.try(:lock!) end end |
#move_possible?(target) ⇒ Boolean
Returns true
it is possible to move node to left/right/child of target
222 223 224 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 222 def move_possible?(target) same_scope?(target) && !is_or_is_ancestor_of?(target) end |
#move_right ⇒ Object Also known as: move_lower
Shorthand method for finding the right sibling and moving to the right of it.
172 173 174 175 176 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 172 def move_right tenacious_transaction do move_to_right_of right_sibling.try(:lock!) end end |
#move_to_child_of(node) ⇒ Object
Move the node to the child of another node
192 193 194 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 192 def move_to_child_of(node) move_to node, :child end |
#move_to_child_with_index(node, index) ⇒ Object
Move the node to the child of another node with specify index
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 197 def move_to_child_with_index(node, index) raise ActiveRecord::ActiveRecordError, "index can't be nil" unless index tenacious_transaction do new_siblings = (node.try(:children) || ordered_tree_scope.roots). reload. lock(true). reject { |root_node| root_node == self } if new_siblings.empty? node ? move_to_child_of(node) : move_to_root elsif new_siblings.count <= index move_to_right_of(new_siblings.last) elsif index >= 0 ? move_to_left_of(new_siblings[index]) : move_to_right_of(new_siblings[index]) end end end |
#move_to_left_of(node) ⇒ Object Also known as: move_to_above_of
Move the node to the left of another node
180 181 182 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 180 def move_to_left_of(node) move_to node, :left end |
#move_to_right_of(node) ⇒ Object Also known as: move_to_bottom_of
Move the node to the left of another node
186 187 188 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 186 def move_to_right_of(node) move_to node, :right end |
#move_to_root ⇒ Object
Move the node to root nodes
217 218 219 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 217 def move_to_root move_to nil, :root end |
#right_sibling ⇒ Object Also known as: lower_item
Returns a right (lower) sibling of the node
149 150 151 152 153 154 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 149 def right_sibling siblings. where( arel[position_column].gt(self[position_column]) ). reorder( arel[position_column].asc ). first end |
#root ⇒ Object
Returns root (not really fast operation)
34 35 36 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 34 def root root? ? self : parent.root end |
#root? ⇒ Boolean
Returns true if this is a root node.
11 12 13 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 11 def root? self[parent_column].nil? end |
#same_scope?(other) ⇒ Boolean
Check if other model is in the same scope
227 228 229 230 231 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 227 def same_scope?(other) scope_column_names.empty? || scope_column_names.all? do |attr| self[attr] == other[attr] end end |
#self_and_ancestors ⇒ Object
Returns the array of all parents and self starting from root
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 39 def self_and_ancestors # 1. recursively load ancestors nodes = [] node = self while node nodes << node node = node.parent end # 2. first ancestor is a root nodes.reverse! # 3. create fake scope ActsAsOrderedTree::Relation::Preloaded.new(self.class). where(:id => nodes.map(&:id).compact). extending(Arrangeable). records(nodes) end |
#self_and_descendants ⇒ Object
Returns a set of itself and all of its nested children
104 105 106 107 108 109 110 111 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 104 def self_and_descendants records = fetch_self_and_descendants ActsAsOrderedTree::Relation::Preloaded.new(self.class). where(:id => records.map(&:id)). extending(Arrangeable). records(records) end |
#self_and_siblings ⇒ Object
Returns the array of all children of the parent, including self
68 69 70 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 68 def self_and_siblings ordered_tree_scope.where(parent_column => self[parent_column]) end |
#siblings ⇒ Object
Returns the array of all children of the parent, except self
73 74 75 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 73 def siblings self_and_siblings.where(arel[:id].not_eq(id)) end |