module OrderedTree::InstanceMethods::List

Public Instance Methods

move_above(sibling = nil) click to toggle source

moves the item above sibling in the list

defaults to the top of the list
# File lib/ordered_tree/instance_methods/list.rb, line 35
def move_above(sibling = nil)
  if sibling
    return if (!self_and_siblings(true).include?(sibling) || (sibling == self))
    if sibling.position_in_list > position_in_list
      move_to(sibling.position_in_list - 1)
    else
      move_to(sibling.position_in_list)
    end
  else
    move_to_top
  end
end
move_higher() click to toggle source

swap with the node above self

# File lib/ordered_tree/instance_methods/list.rb, line 55
def move_higher
  return if position_in_list == 1
  move_to(position_in_list - 1)
end
move_lower() click to toggle source

swap with the node below self

# File lib/ordered_tree/instance_methods/list.rb, line 61
def move_lower
  return if self == self_and_siblings(true).last
  move_to(position_in_list + 1)
end
move_to_bottom() click to toggle source

move to the bottom of the list

# File lib/ordered_tree/instance_methods/list.rb, line 67
def move_to_bottom
  return if self == self_and_siblings(true).last
  move_to(self_and_siblings.last.position_in_list)
end
move_to_top() click to toggle source

move to the top of the list

# File lib/ordered_tree/instance_methods/list.rb, line 49
def move_to_top
  return if position_in_list == 1
  move_to(1)
end
position_in_list() click to toggle source

returns object’s position in the list

the list will either be parent.children,
or self.class.roots

i.e. self.position
# File lib/ordered_tree/instance_methods/list.rb, line 27
def position_in_list
  self[order_column]
end
self_and_siblings(reload = false) click to toggle source

returns an array of the object’s siblings, including itself

return is cached
use self_and_siblings(true) to force a reload
# File lib/ordered_tree/instance_methods/list.rb, line 10
def self_and_siblings(reload = false)
  parent(reload) ? parent.children(reload) : self.class.roots(scope_condition)
end
siblings(reload = false) click to toggle source

returns an array of the object’s siblings, excluding itself

return is cached
use siblings(true) to force a reload
# File lib/ordered_tree/instance_methods/list.rb, line 18
def siblings(reload = false)
  self_and_siblings(reload) - [self]
end

Private Instance Methods

add_to_list() click to toggle source
# File lib/ordered_tree/instance_methods/list.rb, line 99
def add_to_list
  new_position = position_in_list if (1..self_and_siblings(true).size).include?(position_in_list.to_i)
  add_to_list_bottom
  move_to(new_position, true) if new_position
end
add_to_list_bottom() click to toggle source
# File lib/ordered_tree/instance_methods/list.rb, line 105
def add_to_list_bottom
  self[order_column] = self_and_siblings.size + 1
end
move_to(new_position, on_create = false) click to toggle source
# File lib/ordered_tree/instance_methods/list.rb, line 109
def move_to(new_position, on_create = false)
  if parent(true)
    scope = "#{foreign_key_column} = #{parent.id}"
  else
    scope = "#{foreign_key_column} = 0"
  end
  if new_position < position_in_list
    # moving from lower to higher, increment all in between
    # #{order_column} >= #{new_position} AND #{order_column} < #{position_in_list}
    self.class.transaction do
      self.class.#where(order_column => order_column + 1).
        where(scope).
        where("#{order_column} BETWEEN #{new_position} AND #{position_in_list - 1}").
        update_all("#{order_column} = (#{order_column} + 1)")
      if on_create
        self[order_column] = new_position
      else
        update_attribute(order_column, new_position)
      end
    end
  else
    # moving from higher to lower, decrement all in between
    # #{order_column} > #{position_in_list} AND #{order_column} <= #{new_position}
    self.class.transaction do
      self.class.where(scope).
        where("#{order_column} BETWEEN #{position_in_list + 1} AND #{new_position}").
        update_all("#{order_column} = (#{order_column} - 1)")
      update_attribute(order_column, new_position)
    end
  end
end
reorder_roots() click to toggle source
# File lib/ordered_tree/instance_methods/list.rb, line 141
def reorder_roots
  self.class.transaction do
    self.class.roots(scope_condition).each do |root|
      new_position = self.class.roots(scope_condition).index(root) + 1
      root.update_attribute(order_column, new_position) if (root.position_in_list != new_position)
    end
  end
end