class CollectiveIdea::Acts::NestedSet::Move
Attributes
instance[R]
position[R]
target[R]
Public Class Methods
new(target, position, instance)
click to toggle source
# File lib/awesome_nested_set/move.rb, line 7 def initialize(target, position, instance) @target = target @position = position @instance = instance end
Public Instance Methods
move()
click to toggle source
# File lib/awesome_nested_set/move.rb, line 13 def move prevent_impossible_move bound, other_bound = get_boundaries # there would be no change return if bound == right || bound == left # we have defined the boundaries of two non-overlapping intervals, # so sorting puts both the intervals and their boundaries in order a, b, c, d = [left, right, bound, other_bound].sort lock_nodes_between! a, d nested_set_scope_without_default_scope.where(where_statement(a, d)).update_all( conditions(a, b, c, d) ) end
Private Instance Methods
case_condition_for_direction(column_name)
click to toggle source
# File lib/awesome_nested_set/move.rb, line 69 def case_condition_for_direction(column_name) column = send(column_name) "#{column} = CASE " + "WHEN #{column} BETWEEN :a AND :b " + "THEN #{column} + :d - :b " + "WHEN #{column} BETWEEN :c AND :d " + "THEN #{column} + :a - :c " + "ELSE #{column} END, " end
case_condition_for_parent()
click to toggle source
# File lib/awesome_nested_set/move.rb, line 79 def case_condition_for_parent "#{quoted_parent_column_name} = CASE " + "WHEN #{quoted_primary_column_name} = :primary_id THEN :new_parent_id " + "ELSE #{quoted_parent_column_name} END" end
conditions(a, b, c, d)
click to toggle source
# File lib/awesome_nested_set/move.rb, line 48 def conditions(a, b, c, d) _conditions = case_condition_for_direction(:quoted_left_column_name) + case_condition_for_direction(:quoted_right_column_name) + case_condition_for_parent # We want the record to be 'touched' if it timestamps. if @instance.respond_to?(:updated_at) _conditions << ", updated_at = :timestamp" end [ _conditions, { :a => a, :b => b, :c => c, :d => d, :primary_id => instance.primary_id, :new_parent_id => new_parent_id, :timestamp => Time.now.utc } ] end
get_boundaries()
click to toggle source
# File lib/awesome_nested_set/move.rb, line 103 def get_boundaries if (bound = target_bound) > right bound -= 1 other_bound = right + 1 else other_bound = left - 1 end [bound, other_bound] end
lock_nodes_between!(left_bound, right_bound)
click to toggle source
# File lib/awesome_nested_set/move.rb, line 85 def lock_nodes_between!(left_bound, right_bound) # select the rows in the model between a and d, and apply a lock instance_base_class.right_of(left_bound).left_of_right_side(right_bound). select(primary_column_name).lock(true) end
new_parent_id()
click to toggle source
# File lib/awesome_nested_set/move.rb, line 95 def new_parent_id case position when :child then target.primary_id when :root then nil else target[parent_column_name] end end
prevent_impossible_move()
click to toggle source
# File lib/awesome_nested_set/move.rb, line 116 def prevent_impossible_move if !root && !instance.move_possible?(target) raise ImpossibleMove, "Impossible move, target node cannot be inside moved tree." end end
root()
click to toggle source
# File lib/awesome_nested_set/move.rb, line 91 def root position == :root end
target_bound()
click to toggle source
# File lib/awesome_nested_set/move.rb, line 122 def target_bound case position when :child then right(target) when :left then left(target) when :right then right(target) + 1 when :root then nested_set_scope_without_default_scope.pluck(right_column_name).max + 1 else raise ActiveRecord::ActiveRecordError, "Position should be :child, :left, :right or :root ('#{position}' received)." end end
where_statement(left_bound, right_bound)
click to toggle source
# File lib/awesome_nested_set/move.rb, line 43 def where_statement(left_bound, right_bound) instance_arel_table[left_column_name].in(left_bound..right_bound). or(instance_arel_table[right_column_name].in(left_bound..right_bound)) end