328: def move_to(target, position)
329: raise ActiveRecord::ActiveRecordError, "You cannot move a new node" if self.id.nil?
330:
331:
332: cur_left, cur_right = self[acts_as_nested_set_options[:left_column]], self[acts_as_nested_set_options[:right_column]]
333:
334:
335: extent = cur_right - cur_left + 1
336:
337:
338: if !(self.class === target)
339: target = self.class.find(target)
340: end
341: target_left, target_right = target[acts_as_nested_set_options[:left_column]], target[acts_as_nested_set_options[:right_column]]
342:
343:
344: if ((cur_left <= target_left) && (target_left <= cur_right)) or ((cur_left <= target_right) && (target_right <= cur_right))
345: raise ActiveRecord::ActiveRecordError, "Impossible move, target node cannot be inside moved tree."
346: end
347:
348:
349: if position == :child
350: if target_left < cur_left
351: new_left = target_left + 1
352: new_right = target_left + extent
353: else
354: new_left = target_left - extent + 1
355: new_right = target_left
356: end
357: elsif position == :left
358: if target_left < cur_left
359: new_left = target_left
360: new_right = target_left + extent - 1
361: else
362: new_left = target_left - extent
363: new_right = target_left - 1
364: end
365: elsif position == :right
366: if target_right < cur_right
367: new_left = target_right + 1
368: new_right = target_right + extent
369: else
370: new_left = target_right - extent + 1
371: new_right = target_right
372: end
373: else
374: raise ActiveRecord::ActiveRecordError, "Position should be either left or right ('#{position}' received)."
375: end
376:
377:
378: b_left, b_right = [cur_left, new_left].min, [cur_right, new_right].max
379:
380:
381: shift = new_left - cur_left
382:
383:
384: updown = (shift > 0) ? -extent : extent
385:
386:
387: if position == :child
388: new_parent = target.id
389: else
390: new_parent = target[acts_as_nested_set_options[:parent_column]].nil? ? 'NULL' : target[acts_as_nested_set_options[:parent_column]]
391: end
392:
393:
394: self.class.update_all( "#{acts_as_nested_set_options[:left_column]} = CASE \
395: WHEN #{acts_as_nested_set_options[:left_column]} BETWEEN #{cur_left} AND #{cur_right} \
396: THEN #{acts_as_nested_set_options[:left_column]} + #{shift} \
397: WHEN #{acts_as_nested_set_options[:left_column]} BETWEEN #{b_left} AND #{b_right} \
398: THEN #{acts_as_nested_set_options[:left_column]} + #{updown} \
399: ELSE #{acts_as_nested_set_options[:left_column]} END, \
400: #{acts_as_nested_set_options[:right_column]} = CASE \
401: WHEN #{acts_as_nested_set_options[:right_column]} BETWEEN #{cur_left} AND #{cur_right} \
402: THEN #{acts_as_nested_set_options[:right_column]} + #{shift} \
403: WHEN #{acts_as_nested_set_options[:right_column]} BETWEEN #{b_left} AND #{b_right} \
404: THEN #{acts_as_nested_set_options[:right_column]} + #{updown} \
405: ELSE #{acts_as_nested_set_options[:right_column]} END, \
406: #{acts_as_nested_set_options[:parent_column]} = CASE \
407: WHEN #{self.class.primary_key} = #{self.id} \
408: THEN #{new_parent} \
409: ELSE #{acts_as_nested_set_options[:parent_column]} END",
410: acts_as_nested_set_options[:scope] )
411: self.reload
412: end