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 7 def initialize(target, position, instance) 8 @target = target 9 @position = position 10 @instance = instance 11 end
Public Instance Methods
move()
click to toggle source
# File lib/awesome_nested_set/move.rb 13 def move 14 prevent_impossible_move 15 16 bound, other_bound = get_boundaries 17 18 # there would be no change 19 return if bound == right || bound == left 20 21 # we have defined the boundaries of two non-overlapping intervals, 22 # so sorting puts both the intervals and their boundaries in order 23 a, b, c, d = [left, right, bound, other_bound].sort 24 25 lock_nodes_between! a, d 26 27 nested_set_scope_without_default_scope.where(where_statement(a, d)).update_all( 28 conditions(a, b, c, d) 29 ) 30 end
Private Instance Methods
case_condition_for_direction(column_name)
click to toggle source
# File lib/awesome_nested_set/move.rb 81 def case_condition_for_direction(column_name) 82 column = send(column_name) 83 "#{column} = CASE " + 84 "WHEN #{column} BETWEEN :a AND :b " + 85 "THEN #{column} + :d - :b " + 86 "WHEN #{column} BETWEEN :c AND :d " + 87 "THEN #{column} + :a - :c " + 88 "ELSE #{column} END, " 89 end
case_condition_for_parent()
click to toggle source
# File lib/awesome_nested_set/move.rb 91 def case_condition_for_parent 92 "#{quoted_parent_column_name} = CASE " + 93 "WHEN #{quoted_primary_column_name} = :primary_id THEN :new_parent_id " + 94 "ELSE #{quoted_parent_column_name} END" 95 end
conditions(a, b, c, d)
click to toggle source
# File lib/awesome_nested_set/move.rb 60 def conditions(a, b, c, d) 61 _conditions = case_condition_for_direction(:quoted_left_column_name) + 62 case_condition_for_direction(:quoted_right_column_name) + 63 case_condition_for_parent 64 65 # We want the record to be 'touched' if it timestamps. 66 if @instance.respond_to?(:updated_at) 67 _conditions << ", updated_at = :timestamp" 68 end 69 70 [ 71 _conditions, 72 { 73 :a => a, :b => b, :c => c, :d => d, 74 :primary_id => instance.primary_id, 75 :new_parent_id => new_parent_id, 76 :timestamp => Time.now.utc 77 } 78 ] 79 end
get_boundaries()
click to toggle source
# File lib/awesome_nested_set/move.rb 117 def get_boundaries 118 if (bound = target_bound) > right 119 bound -= 1 120 other_bound = right + 1 121 else 122 other_bound = left - 1 123 end 124 [bound, other_bound] 125 end
lock_nodes_between!(left_bound, right_bound)
click to toggle source
# File lib/awesome_nested_set/move.rb 97 def lock_nodes_between!(left_bound, right_bound) 98 # select the rows in the model between a and d, and apply a lock 99 instance_base_class.default_scoped.nested_set_scope. 100 right_of(left_bound).left_of_right_side(right_bound). 101 select(primary_column_name). 102 lock(true) 103 end
new_parent_id()
click to toggle source
# File lib/awesome_nested_set/move.rb 109 def new_parent_id 110 case position 111 when :child then target.primary_id 112 when :root then nil 113 else target[parent_column_name] 114 end 115 end
prevent_impossible_move()
click to toggle source
# File lib/awesome_nested_set/move.rb 130 def prevent_impossible_move 131 if !root && !instance.move_possible?(target) 132 error_msg = "Impossible move, target node (#{target.class.name},ID: #{target.id}) 133 cannot be inside moved tree (#{instance.class.name},ID: #{instance.id})." 134 raise ImpossibleMove, error_msg 135 end 136 end
root()
click to toggle source
# File lib/awesome_nested_set/move.rb 105 def root 106 position == :root 107 end
target_bound()
click to toggle source
# File lib/awesome_nested_set/move.rb 138 def target_bound 139 case position 140 when :child then right(target) 141 when :left then left(target) 142 when :right then right(target) + 1 143 when :root then nested_set_scope_without_default_scope.pluck(right_column_name).max + 1 144 else raise ActiveRecord::ActiveRecordError, "Position should be :child, :left, :right or :root ('#{position}' received)." 145 end 146 end
where_statement(left_bound, right_bound)
click to toggle source
# File lib/awesome_nested_set/move.rb 43 def where_statement(left_bound, right_bound) 44 instance_arel_table[left_column_name].between(left_bound..right_bound). 45 or(instance_arel_table[right_column_name].between(left_bound..right_bound)) 46 end