1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

acts_as_list plays nicely with inheritance by remembering the class which declared it. Closes #2811.

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@2964 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
Jeremy Kemper 2005-11-10 06:19:50 +00:00
parent adba181060
commit b84a7beb98
5 changed files with 196 additions and 12 deletions

View file

@ -1,5 +1,7 @@
*SVN*
* acts_as_list plays nicely with inheritance by remembering the class which declared it. #2811 [rephorm@rephorm.com]
* Fix sqlite adaptor's detection of missing dbfile or database declaration. [Nicholas Seckar]
* Fixed acts_as_list for definitions without an explicit :order #2803 [jonathan@bluewire.net.nz]

View file

@ -54,6 +54,10 @@ module ActiveRecord
class_eval <<-EOV
include ActiveRecord::Acts::List::InstanceMethods
def acts_as_list_class
#{self.name}
end
def position_column
'#{configuration[:column]}'
end
@ -78,7 +82,7 @@ module ActiveRecord
def move_lower
return unless lower_item
self.class.transaction do
acts_as_list_class.transaction do
lower_item.decrement_position
increment_position
end
@ -87,7 +91,7 @@ module ActiveRecord
def move_higher
return unless higher_item
self.class.transaction do
acts_as_list_class.transaction do
higher_item.increment_position
decrement_position
end
@ -95,7 +99,7 @@ module ActiveRecord
def move_to_bottom
return unless in_list?
self.class.transaction do
acts_as_list_class.transaction do
decrement_positions_on_lower_items
assume_bottom_position
end
@ -103,7 +107,7 @@ module ActiveRecord
def move_to_top
return unless in_list?
self.class.transaction do
acts_as_list_class.transaction do
increment_positions_on_higher_items
assume_top_position
end
@ -135,14 +139,14 @@ module ActiveRecord
def higher_item
return nil unless in_list?
self.class.find(:first, :conditions =>
acts_as_list_class.find(:first, :conditions =>
"#{scope_condition} AND #{position_column} = #{(send(position_column).to_i - 1).to_s}"
)
end
def lower_item
return nil unless in_list?
self.class.find(:first, :conditions =>
acts_as_list_class.find(:first, :conditions =>
"#{scope_condition} AND #{position_column} = #{(send(position_column).to_i + 1).to_s}"
)
end
@ -171,7 +175,7 @@ module ActiveRecord
def bottom_item(except = nil)
conditions = scope_condition
conditions = "#{conditions} AND id != #{except.id}" if except
self.class.find(:first, :conditions => conditions, :order => "#{position_column} DESC")
acts_as_list_class.find(:first, :conditions => conditions, :order => "#{position_column} DESC")
end
def assume_bottom_position
@ -184,7 +188,7 @@ module ActiveRecord
# This has the effect of moving all the higher items up one.
def decrement_positions_on_higher_items(position)
self.class.update_all(
acts_as_list_class.update_all(
"#{position_column} = (#{position_column} - 1)", "#{scope_condition} AND #{position_column} <= #{position}"
)
end
@ -192,7 +196,7 @@ module ActiveRecord
# This has the effect of moving all the lower items up one.
def decrement_positions_on_lower_items
return unless in_list?
self.class.update_all(
acts_as_list_class.update_all(
"#{position_column} = (#{position_column} - 1)", "#{scope_condition} AND #{position_column} > #{send(position_column).to_i}"
)
end
@ -200,20 +204,20 @@ module ActiveRecord
# This has the effect of moving all the higher items down one.
def increment_positions_on_higher_items
return unless in_list?
self.class.update_all(
acts_as_list_class.update_all(
"#{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(
acts_as_list_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(
acts_as_list_class.update_all(
"#{position_column} = (#{position_column} + 1)", "#{scope_condition}"
)
end

View file

@ -16,6 +16,12 @@ class ListMixin < Mixin
def self.table_name() "mixins" end
end
class ListMixinSub1 < ListMixin
end
class ListMixinSub2 < ListMixin
end
class ListWithStringScopeMixin < ActiveRecord::Base
acts_as_list :column => "pos", :scope => 'parent_id = #{parent_id}'

View file

@ -78,3 +78,12 @@ tree_<%= set[0] %>:
root_id: 42
<% end %>
# subclasses of list items
<% (1..4).each do |i| %>
list_sub_<%= i %>:
id: <%= i + 5000 %>
pos: <%= i %>
parent_id: 5000
type: <%= (i % 2 == 1) ? ListMixinSub1 : ListMixinSub2 %>
<% end %>

View file

@ -195,6 +195,7 @@ class ListTest < Test::Unit::TestCase
new2.move_higher
assert_equal [new2, new1, new3], ListMixin.find(:all, :conditions => 'parent_id IS NULL', :order => 'pos')
end
end
class TreeTest < Test::Unit::TestCase
@ -353,3 +354,165 @@ class TouchTest < Test::Unit::TestCase
end
end
class ListSubTest < Test::Unit::TestCase
fixtures :mixins
def test_reordering
assert_equal [mixins(:list_sub_1),
mixins(:list_sub_2),
mixins(:list_sub_3),
mixins(:list_sub_4)],
ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos')
mixins(:list_sub_2).move_lower
assert_equal [mixins(:list_sub_1),
mixins(:list_sub_3),
mixins(:list_sub_2),
mixins(:list_sub_4)],
ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos')
mixins(:list_sub_2).move_higher
assert_equal [mixins(:list_sub_1),
mixins(:list_sub_2),
mixins(:list_sub_3),
mixins(:list_sub_4)],
ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos')
mixins(:list_sub_1).move_to_bottom
assert_equal [mixins(:list_sub_2),
mixins(:list_sub_3),
mixins(:list_sub_4),
mixins(:list_sub_1)],
ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos')
mixins(:list_sub_1).move_to_top
assert_equal [mixins(:list_sub_1),
mixins(:list_sub_2),
mixins(:list_sub_3),
mixins(:list_sub_4)],
ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos')
mixins(:list_sub_2).move_to_bottom
assert_equal [mixins(:list_sub_1),
mixins(:list_sub_3),
mixins(:list_sub_4),
mixins(:list_sub_2)],
ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos')
mixins(:list_sub_4).move_to_top
assert_equal [mixins(:list_sub_4),
mixins(:list_sub_1),
mixins(:list_sub_3),
mixins(:list_sub_2)],
ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos')
end
def test_move_to_bottom_with_next_to_last_item
assert_equal [mixins(:list_sub_1),
mixins(:list_sub_2),
mixins(:list_sub_3),
mixins(:list_sub_4)],
ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos')
mixins(:list_sub_3).move_to_bottom
assert_equal [mixins(:list_sub_1),
mixins(:list_sub_2),
mixins(:list_sub_4),
mixins(:list_sub_3)],
ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos')
end
def test_next_prev
assert_equal mixins(:list_sub_2), mixins(:list_sub_1).lower_item
assert_nil mixins(:list_sub_1).higher_item
assert_equal mixins(:list_sub_3), mixins(:list_sub_4).higher_item
assert_nil mixins(:list_sub_4).lower_item
end
def test_injection
item = ListMixin.new("parent_id"=>1)
assert_equal "parent_id = 1", item.scope_condition
assert_equal "pos", item.position_column
end
def test_insert_at
new = ListMixin.create("parent_id" => 20)
assert_equal 1, new.pos
new = ListMixinSub1.create("parent_id" => 20)
assert_equal 2, new.pos
new = ListMixinSub2.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
new5 = ListMixinSub1.create("parent_id" => 20)
assert_equal 5, new5.pos
new5.insert_at(1)
assert_equal 1, new5.pos
new4.reload
assert_equal 5, new4.pos
end
def test_delete_middle
assert_equal [mixins(:list_sub_1),
mixins(:list_sub_2),
mixins(:list_sub_3),
mixins(:list_sub_4)],
ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos')
mixins(:list_sub_2).destroy
assert_equal [mixins(:list_sub_1, :reload),
mixins(:list_sub_3, :reload),
mixins(:list_sub_4, :reload)],
ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos')
assert_equal 1, mixins(:list_sub_1).pos
assert_equal 2, mixins(:list_sub_3).pos
assert_equal 3, mixins(:list_sub_4).pos
mixins(:list_sub_1).destroy
assert_equal [mixins(:list_sub_3, :reload),
mixins(:list_sub_4, :reload)],
ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos')
assert_equal 1, mixins(:list_sub_3).pos
assert_equal 2, mixins(:list_sub_4).pos
end
end