From 8d3ff3abc757dee8c6538c1f26f839882786a5cc Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Fri, 12 Jan 2007 05:33:09 +0000 Subject: acts_as_nested_set works with single-table inheritance. Closes #6030. git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@5889 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- activerecord/CHANGELOG | 2 ++ activerecord/lib/active_record/acts/nested_set.rb | 20 ++++++++++---------- activerecord/test/fixtures/mixin.rb | 10 ++++++++++ activerecord/test/fixtures/mixins.yml | 18 ++++++++++++++++++ activerecord/test/mixin_nested_set_test.rb | 16 ++++++++++++++-- 5 files changed, 54 insertions(+), 12 deletions(-) diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG index 1c6988765c..513179931a 100644 --- a/activerecord/CHANGELOG +++ b/activerecord/CHANGELOG @@ -1,5 +1,7 @@ *SVN* +* acts_as_nested_set works with single-table inheritance. #6030 [Josh Susser] + * PostgreSQL: use a subselect to correctly perform eager finds with :limit and :order. #4668 [eventualbuddha] * Pass a range in :conditions to use the SQL BETWEEN operator. #6974 [dcmanges] diff --git a/activerecord/lib/active_record/acts/nested_set.rb b/activerecord/lib/active_record/acts/nested_set.rb index 9d5bcf4d3d..09bf1c39af 100644 --- a/activerecord/lib/active_record/acts/nested_set.rb +++ b/activerecord/lib/active_record/acts/nested_set.rb @@ -163,9 +163,9 @@ module ActiveRecord child[left_col_name] = right_bound child[right_col_name] = right_bound + 1 self[right_col_name] += 2 - self.class.transaction { - self.class.update_all( "#{left_col_name} = (#{left_col_name} + 2)", "#{scope_condition} AND #{left_col_name} >= #{right_bound}" ) - self.class.update_all( "#{right_col_name} = (#{right_col_name} + 2)", "#{scope_condition} AND #{right_col_name} >= #{right_bound}" ) + self.class.base_class.transaction { + self.class.base_class.update_all( "#{left_col_name} = (#{left_col_name} + 2)", "#{scope_condition} AND #{left_col_name} >= #{right_bound}" ) + self.class.base_class.update_all( "#{right_col_name} = (#{right_col_name} + 2)", "#{scope_condition} AND #{right_col_name} >= #{right_bound}" ) self.save child.save } @@ -180,17 +180,17 @@ module ActiveRecord # Returns a set of itself and all of its nested children def full_set - self.class.find(:all, :conditions => "#{scope_condition} AND (#{left_col_name} BETWEEN #{self[left_col_name]} and #{self[right_col_name]})" ) + self.class.base_class.find(:all, :conditions => "#{scope_condition} AND (#{left_col_name} BETWEEN #{self[left_col_name]} and #{self[right_col_name]})" ) end # Returns a set of all of its children and nested children def all_children - self.class.find(:all, :conditions => "#{scope_condition} AND (#{left_col_name} > #{self[left_col_name]}) and (#{right_col_name} < #{self[right_col_name]})" ) + self.class.base_class.find(:all, :conditions => "#{scope_condition} AND (#{left_col_name} > #{self[left_col_name]}) and (#{right_col_name} < #{self[right_col_name]})" ) end # Returns a set of only this entry's immediate children def direct_children - self.class.find(:all, :conditions => "#{scope_condition} and #{parent_column} = #{self.id}") + self.class.base_class.find(:all, :conditions => "#{scope_condition} and #{parent_column} = #{self.id}") end # Prunes a branch off of the tree, shifting all of the elements on the right @@ -199,10 +199,10 @@ module ActiveRecord return if self[right_col_name].nil? || self[left_col_name].nil? dif = self[right_col_name] - self[left_col_name] + 1 - self.class.transaction { - self.class.delete_all( "#{scope_condition} and #{left_col_name} > #{self[left_col_name]} and #{right_col_name} < #{self[right_col_name]}" ) - self.class.update_all( "#{left_col_name} = (#{left_col_name} - #{dif})", "#{scope_condition} AND #{left_col_name} >= #{self[right_col_name]}" ) - self.class.update_all( "#{right_col_name} = (#{right_col_name} - #{dif} )", "#{scope_condition} AND #{right_col_name} >= #{self[right_col_name]}" ) + self.class.base_class.transaction { + self.class.base_class.delete_all( "#{scope_condition} and #{left_col_name} > #{self[left_col_name]} and #{right_col_name} < #{self[right_col_name]}" ) + self.class.base_class.update_all( "#{left_col_name} = (#{left_col_name} - #{dif})", "#{scope_condition} AND #{left_col_name} >= #{self[right_col_name]}" ) + self.class.base_class.update_all( "#{right_col_name} = (#{right_col_name} - #{dif} )", "#{scope_condition} AND #{right_col_name} >= #{self[right_col_name]}" ) } end end diff --git a/activerecord/test/fixtures/mixin.rb b/activerecord/test/fixtures/mixin.rb index 1f200da62d..7f877a8ce8 100644 --- a/activerecord/test/fixtures/mixin.rb +++ b/activerecord/test/fixtures/mixin.rb @@ -51,3 +51,13 @@ class NestedSetWithSymbolScope < Mixin def self.table_name() "mixins" end end + +class NestedSetSuperclass < Mixin + acts_as_nested_set :scope => :root + + def self.table_name() "mixins" end +end + +class NestedSetSubclass < NestedSetSuperclass + +end diff --git a/activerecord/test/fixtures/mixins.yml b/activerecord/test/fixtures/mixins.yml index d7a0b97295..881b97c1d2 100644 --- a/activerecord/test/fixtures/mixins.yml +++ b/activerecord/test/fixtures/mixins.yml @@ -77,6 +77,24 @@ set_<%= counter %>: type: NestedSet <% end %> +# Nested set with STI +<% +[ [3100, 0, 1, 10, "NestedSetSuperclass"], + [3101, 3100, 2, 5, "NestedSetSubclass"], + [3102, 3101, 3, 4, "NestedSetSuperclass"], + [3103, 3100, 6, 9, "NestedSetSuperclass"], + [3104, 3103, 7, 8, "NestedSetSubclass"] +].each do |sti| %> +sti_set_<%= sti[0] %>: + id: <%= sti[0] %> + parent_id: <%= sti[1] %> + lft: <%= sti[2] %> + rgt: <%= sti[3] %> + type: <%= sti[4] %> + root_id: 3100 + +<% end %> + # Big old set <% [[4001, 0, 1, 20], diff --git a/activerecord/test/mixin_nested_set_test.rb b/activerecord/test/mixin_nested_set_test.rb index 8764a6ac49..7ed9075bda 100644 --- a/activerecord/test/mixin_nested_set_test.rb +++ b/activerecord/test/mixin_nested_set_test.rb @@ -178,7 +178,19 @@ class MixinNestedSetTest < Test::Unit::TestCase mixins(:set_1).add_child mixins(:set_4) assert_equal( 3, mixins(:set_1).all_children.length ) - - + end + + def test_inheritance + parent = mixins(:sti_set_3100) + child = mixins(:sti_set_3101) + grandchild = mixins(:sti_set_3102) + assert_equal 5, parent.full_set.size + assert_equal 2, child.full_set.size + assert_equal 4, parent.all_children.size + assert_equal 1, child.all_children.size + assert_equal 2, parent.direct_children.size + assert_equal 1, child.direct_children.size + child.destroy + assert_equal 3, parent.full_set.size end end -- cgit v1.2.3