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
trueif 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
trueif 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
trueit 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
58 59 60 61 62 63 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 58 def ancestors records = self_and_ancestors - [self] scope = self_and_ancestors.where(arel[:id].not_eq(id)) scope.records(records) end |
#branch? ⇒ Boolean
23 24 25 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 23 def branch? !leaf? end |
#child? ⇒ Boolean
Returns true is this is a child node
28 29 30 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 28 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)
92 93 94 95 96 97 98 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 92 def descendants records = fetch_self_and_descendants - [self] ActsAsOrderedTree::Relation::Preloaded.new(self.class). where(:id => records.map(&:id)). records(records) end |
#first? ⇒ Boolean
Return true if this object is the first in the list.
126 127 128 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 126 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
155 156 157 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 155 def insert_at(position = 1) move_to_child_with_index(parent, position - 1) end |
#is_ancestor_of?(other) ⇒ Boolean
117 118 119 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 117 def is_ancestor_of?(other) other.is_descendant_of? self end |
#is_descendant_of?(other) ⇒ Boolean
109 110 111 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 109 def is_descendant_of?(other) ancestors.include? other end |
#is_or_is_ancestor_of?(other) ⇒ Boolean
121 122 123 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 121 def is_or_is_ancestor_of?(other) other.is_or_is_descendant_of? self end |
#is_or_is_descendant_of?(other) ⇒ Boolean
113 114 115 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 113 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.
131 132 133 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 131 def last? !right_sibling end |
#leaf? ⇒ Boolean
Returns true if this is the end of a branch.
15 16 17 18 19 20 21 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 15 def leaf? persisted? && if children_counter_cache_column self[children_counter_cache_column] == 0 else children.count == 0 end end |
#left_sibling ⇒ Object Also known as: higher_item
Returns a left (upper) sibling of the node
136 137 138 139 140 141 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 136 def left_sibling siblings. where( arel[position_column].lt(self[position_column]) ). reorder( arel[position_column].desc ). first end |
#level ⇒ Object
75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 75 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.
160 161 162 163 164 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 160 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
218 219 220 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 218 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.
168 169 170 171 172 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 168 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
188 189 190 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 188 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
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 193 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
176 177 178 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 176 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
182 183 184 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 182 def move_to_right_of(node) move_to node, :right end |
#move_to_root ⇒ Object
Move the node to root nodes
213 214 215 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 213 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
145 146 147 148 149 150 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 145 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)
33 34 35 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 33 def root root? ? self : parent.root end |
#root? ⇒ Boolean
Returns true if this is a root node.
10 11 12 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 10 def root? self[parent_column].nil? end |
#same_scope?(other) ⇒ Boolean
Check if other model is in the same scope
223 224 225 226 227 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 223 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
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 38 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)). records(nodes) end |
#self_and_descendants ⇒ Object
Returns a set of itself and all of its nested children
101 102 103 104 105 106 107 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 101 def self_and_descendants records = fetch_self_and_descendants ActsAsOrderedTree::Relation::Preloaded.new(self.class). where(:id => records.map(&:id)). records(records) end |
#self_and_siblings ⇒ Object
Returns the array of all children of the parent, including self
66 67 68 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 66 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
71 72 73 |
# File 'lib/acts_as_ordered_tree/instance_methods.rb', line 71 def siblings self_and_siblings.where(arel[:id].not_eq(id)) end |