From ed46cc3058ac9406f61220c9720c51f4edd172f9 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 17 Apr 2005 06:50:17 +0000 Subject: Added insert_at(position) to acts_as_list #1083 [DeLynnB] git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@1179 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- activerecord/CHANGELOG | 2 ++ activerecord/lib/active_record/acts/list.rb | 32 +++++++++++++++++++++++++---- activerecord/test/mixin_test.rb | 30 ++++++++++++++++++++++++--- 3 files changed, 57 insertions(+), 7 deletions(-) (limited to 'activerecord') diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG index 217413999e..db64507f3e 100644 --- a/activerecord/CHANGELOG +++ b/activerecord/CHANGELOG @@ -1,5 +1,7 @@ *SVN* +* Added insert_at(position) to acts_as_list #1083 [DeLynnB] + * Removed the default order by id on has_and_belongs_to_many queries as it could kill performance on large sets (you can still specify by hand with :order) * Fixed that Base.silence should restore the old logger level when done, not just set it to DEBUG #1084 [yon@milliped.com] diff --git a/activerecord/lib/active_record/acts/list.rb b/activerecord/lib/active_record/acts/list.rb index abd295d4e9..4d649726b2 100644 --- a/activerecord/lib/active_record/acts/list.rb +++ b/activerecord/lib/active_record/acts/list.rb @@ -71,6 +71,10 @@ module ActiveRecord # lower in the list of all chapters. Likewise, chapter.first? would return true if that chapter is # the first in the list of all chapters. module InstanceMethods + def insert_at(position = 1) + position == 1 ? add_to_list_top : insert_at_position(position) + end + def move_lower return unless lower_item @@ -107,7 +111,6 @@ module ActiveRecord decrement_positions_on_lower_items end - def increment_position update_attribute position_column, self.send(position_column).to_i + 1 end @@ -168,24 +171,45 @@ module ActiveRecord update_attribute(position_column, 1) end + # This has the effect of moving all the higher items up one. + def decrement_positions_on_higher_items(position) + self.class.update_all( + "#{position_column} = (#{position_column} - 1)", "#{scope_condition} AND #{position_column} <= #{position}" + ) + end + # This has the effect of moving all the lower items up one. def decrement_positions_on_lower_items self.class.update_all( - "#{position_column} = (#{position_column} - 1)", "#{scope_condition} AND #{position_column} > #{send(position_column).to_i}" + "#{position_column} = (#{position_column} - 1)", "#{scope_condition} AND #{position_column} > #{send(position_column).to_i}" ) end - + + # This has the effect of moving all the higher items down one. def increment_positions_on_higher_items self.class.update_all( - "#{position_column} = (#{position_column} + 1)", "#{scope_condition} AND #{position_column} < #{send(position_column).to_i}" + "#{position_column} = (#{position_column} + 1)", "#{scope_condition} AND #{position_column} < #{send(position_column).to_i}" ) end + # This has the effect of moving all the lower items down one. + def increment_positions_on_lower_items(position) + self.class.update_all( + "#{position_column} = (#{position_column} + 1)", "#{scope_condition} AND #{position_column} >= #{position}" + ) + end + def increment_positions_on_all_items self.class.update_all( "#{position_column} = (#{position_column} + 1)", "#{scope_condition}" ) end + + def insert_at_position(position) + remove_from_list + increment_positions_on_lower_items(position) + self.update_attribute(position_column, position) + end end end end diff --git a/activerecord/test/mixin_test.rb b/activerecord/test/mixin_test.rb index c58607f86c..52aa95117b 100644 --- a/activerecord/test/mixin_test.rb +++ b/activerecord/test/mixin_test.rb @@ -5,7 +5,7 @@ require 'fixtures/mixin' class ListTest < Test::Unit::TestCase fixtures :mixins - + def test_reordering assert_equal [@mixins['list_1'].find, @@ -100,6 +100,32 @@ class ListTest < Test::Unit::TestCase assert new.first? assert new.last? end + + def test_insert_at + new = ListMixin.create("parent_id" => 20) + assert_equal 1, new.pos + + new = ListMixin.create("parent_id" => 20) + assert_equal 2, new.pos + + new = ListMixin.create("parent_id" => 20) + assert_equal 3, new.pos + + new4 = ListMixin.create("parent_id" => 20) + assert_equal 4, new4.pos + + new4.insert_at(3) + assert_equal 3, new4.pos + + new.reload + assert_equal 4, new.pos + + new.insert_at(2) + assert_equal 2, new.pos + + new4.reload + assert_equal 4, new4.pos + end def test_delete_middle @@ -186,7 +212,6 @@ class TreeTest < Test::Unit::TestCase assert @tree_1.children.include?(@tree_2) assert @tree_1.children.include?(@tree_4) end - end @@ -229,7 +254,6 @@ class TouchTest < Test::Unit::TestCase end - def test_create_turned_off Mixin.record_timestamps = false -- cgit v1.2.3