Browse files

Changed test suite to run independently of Rails application

  • Loading branch information...
1 parent 48ddb2e commit f1955bb5704b475f31076d6c8b69822cdc8f135d @stefankroes stefankroes committed Sep 18, 2010
View
2 README.rdoc
@@ -1,6 +1,6 @@
= Ancestry
-Ancestry is a gem/plugin that allows the records of a Ruby on Rails ActiveRecord model to be organised as a tree structure (or hierarchy). It uses a single, intuitively formatted database column, using a variation on the materialised path pattern. It exposes all the standard tree structure relations (ancestors, parent, root, children, siblings, descendants) and all of them can be fetched in a single sql query. Additional features are STI support, named_scopes, depth caching, depth constraints, easy migration from older plugins/gems, integrity checking, integrity restoration, arrangement of (sub)tree into hashes and different strategies for dealing with orphaned records.
+Ancestry is a gem/plugin that allows the records of a Ruby on Rails ActiveRecord model to be organised as a tree structure (or hierarchy). It uses a single, intuitively formatted database column, using a variation on the materialised path pattern. It exposes all the standard tree structure relations (ancestors, parent, root, children, siblings, descendants) and all of them can be fetched in a single sql query. Additional features are STI support, scopes, depth caching, depth constraints, easy migration from older plugins/gems, integrity checking, integrity restoration, arrangement of (sub)tree into hashes and different strategies for dealing with orphaned records.
= Installation
View
15 ancestry.gemspec
@@ -5,14 +5,25 @@ Gem::Specification.new do |s|
s.description = 'Organise ActiveRecord model into a tree structure'
s.summary = 'Ancestry allows the records of a ActiveRecord model to be organised in a tree structure, using a single, intuitively formatted database column. It exposes all the standard tree structure relations (ancestors, parent, root, children, siblings, descendants) and all of them can be fetched in a single sql query. Additional features are named_scopes, integrity checking, integrity restoration, arrangement of (sub)tree into hashes and different strategies for dealing with orphaned records.'
- s.version = '1.2.0'
+ s.version = '1.3.0'
s.date = '2010-01-27'
s.author = 'Stefan Kroes'
s.email = 's.a.kroes@gmail.com'
s.homepage = 'http://github.com/stefankroes/ancestry'
- s.files = FileList['ancestry.gemspec', '*.rb', 'lib/**/*.rb', 'test/*', 'Rakefile', 'MIT-LICENSE', 'README.rdoc']
+ s.files = FileList[
+ 'ancestry.gemspec',
+ 'init.rb',
+ 'install.rb',
+ 'lib/ancestry.rb',
+ 'lib/ancestry/has_ancestry.rb',
+ 'lib/ancestry/exceptions.rb',
+ 'lib/ancestry/class_methods.rb',
+ 'lib/ancestry/instance_methods.rb',
+ 'MIT-LICENSE',
+ 'README.rdoc'
+ ]
s.add_dependency 'activerecord', '>= 2.1.0'
end
View
1 install.rb
@@ -1,2 +1 @@
-# Install hook code here
puts "Thank you for installing Ancestry. You can visit http://github.com/stefankroes/ancestry to read the documentation."
View
4 lib/ancestry/class_methods.rb
@@ -53,7 +53,7 @@ def check_ancestry_integrity!
# For each node ...
self.base_class.all.each do |node|
# ... check validity of ancestry column
- if !node.valid? and node.errors.invalid?(node.class.ancestry_column)
+ if !node.valid? and node.errors[node.class.ancestry_column].blank?
raise Ancestry::AncestryIntegrityException.new("Invalid format for ancestry column of node #{node.id}: #{node.read_attribute node.ancestry_column}.")
end
# ... check that all ancestors exist
@@ -78,7 +78,7 @@ def restore_ancestry_integrity!
# For each node ...
self.base_class.all.each do |node|
# ... set its ancestry to nil if invalid
- if node.errors.invalid? node.class.ancestry_column
+ if node.errors[node.class.ancestry_column].blank?
node.without_ancestry_callbacks do
node.update_attributes :ancestry => nil
end
View
22 lib/ancestry/has_ancestry.rb
@@ -36,15 +36,19 @@ def has_ancestry options = {}
# Validate that the ancestor ids don't include own id
validate :ancestry_exclude_self
+ # Workaround to support Rails 2
+ scope_method = if ActiveRecord::VERSION::MAJOR < 3 then :named_scope else :scope end
+
+
# Named scopes
- named_scope :roots, :conditions => {ancestry_column => nil}
- named_scope :ancestors_of, lambda { |object| {:conditions => to_node(object).ancestor_conditions} }
- named_scope :children_of, lambda { |object| {:conditions => to_node(object).child_conditions} }
- named_scope :descendants_of, lambda { |object| {:conditions => to_node(object).descendant_conditions} }
- named_scope :subtree_of, lambda { |object| {:conditions => to_node(object).subtree_conditions} }
- named_scope :siblings_of, lambda { |object| {:conditions => to_node(object).sibling_conditions} }
- named_scope :ordered_by_ancestry, :order => "(case when #{ancestry_column} is null then 0 else 1 end), #{ancestry_column}"
- named_scope :ordered_by_ancestry_and, lambda { |order| {:order => "(case when #{ancestry_column} is null then 0 else 1 end), #{ancestry_column}, #{order}"} }
+ send scope_method, :roots, :conditions => {ancestry_column => nil}
+ send scope_method, :ancestors_of, lambda { |object| {:conditions => to_node(object).ancestor_conditions} }
+ send scope_method, :children_of, lambda { |object| {:conditions => to_node(object).child_conditions} }
+ send scope_method, :descendants_of, lambda { |object| {:conditions => to_node(object).descendant_conditions} }
+ send scope_method, :subtree_of, lambda { |object| {:conditions => to_node(object).subtree_conditions} }
+ send scope_method, :siblings_of, lambda { |object| {:conditions => to_node(object).sibling_conditions} }
+ send scope_method, :ordered_by_ancestry, :order => "(case when #{ancestry_column} is null then 0 else 1 end), #{ancestry_column}"
+ send scope_method, :ordered_by_ancestry_and, lambda { |order| {:order => "(case when #{ancestry_column} is null then 0 else 1 end), #{ancestry_column}, #{order}"} }
# Update descendants with new ancestry before save
before_save :update_descendants_with_new_ancestry
@@ -67,7 +71,7 @@ def has_ancestry options = {}
# Create named scopes for depth
{:before_depth => '<', :to_depth => '<=', :at_depth => '=', :from_depth => '>=', :after_depth => '>'}.each do |scope_name, operator|
- named_scope scope_name, lambda { |depth|
+ send scope_method, scope_name, lambda { |depth|
raise Ancestry::AncestryException.new("Named scope '#{scope_name}' is only available when depth caching is enabled.") unless options[:cache_depth]
{:conditions => ["#{depth_cache_column} #{operator} ?", depth]}
}
View
15 lib/ancestry/instance_methods.rb
@@ -1,8 +1,8 @@
module Ancestry
- module InstanceMethods
+ module InstanceMethods
# Validate that the ancestors don't include itself
def ancestry_exclude_self
- errors.add_to_base "#{self.class.name.humanize} cannot be a descendant of itself." if ancestor_ids.include? self.id
+ add_error_to_base "#{self.class.name.humanize} cannot be a descendant of itself." if ancestor_ids.include? self.id
end
# Update descendants with new ancestry
@@ -205,5 +205,16 @@ def without_ancestry_callbacks
def ancestry_callbacks_disabled?
!!@disable_ancestry_callbacks
end
+
+ private
+
+ # Workaround to support Rails 2
+ def add_error_to_base error
+ if ActiveRecord::VERSION::MAJOR < 3
+ errors.add_to_base error
+ else
+ errors[:base] << error
+ end
+ end
end
end
View
12 test/database.yml
@@ -1,17 +1,17 @@
sqlite:
adapter: sqlite
- database: vendor/plugins/ancestry/test/ancestry_plugin.sqlite.db
+ database: ":memory:"
sqlite3:
adapter: sqlite3
- database: vendor/plugins/ancestry/test/ancestry_plugin.sqlite3.db
+ database: ":memory:"
postgresql:
adapter: postgresql
- database: ancestry_development
+ database: ancestry_test
username: ancestry
password: ancestry
mysql:
adapter: mysql
host: localhost
- username: ancestry_plugin_test
- password: ancestry_plugin_test
- database: ancestry_plugin_test
+ database: ancestry_test
+ username: ancestry
+ password: ancestry
View
887 test/has_ancestry_test.rb
@@ -1,84 +1,118 @@
-require File.dirname(__FILE__) + '/test_helper.rb'
-
-# Setup the required models for all test cases
-
-class TestNode < ActiveRecord::Base
- has_ancestry :cache_depth => true, :depth_cache_column => :depth_cache
-end
-
-class AlternativeTestNode < ActiveRecord::Base
- has_ancestry :ancestry_column => :alternative_ancestry, :orphan_strategy => :rootify
-end
-
-class ActsAsTreeTestNode < ActiveRecord::Base
- acts_as_tree
-end
-
-class ParentIdTestNode < ActiveRecord::Base
-end
-
-class TestNodeSub1 < TestNode
-end
-
-class TestNodeSub2 < TestNode
-end
-
-class ActsAsTreeTest < ActiveSupport::TestCase
- load_schema
+require 'rubygems'
+Gem.activate 'activerecord', ENV['ar'] || '3.0.0'
+require 'active_record'
+require 'active_support/test_case'
+require 'test/unit'
+require 'ancestry'
+
+class AncestryTestDatabase
+ def self.setup
+ ActiveRecord::Base.logger
+ ActiveRecord::Base.establish_connection YAML.load(File.open(File.join(File.dirname(__FILE__), 'database.yml')).read)[ENV['db'] || 'sqlite3']
+ end
- def setup_test_nodes model, level, quantity
- model.delete_all
- create_test_nodes model, nil, level, quantity
+ def self.with_model options = {}
+ depth = options.delete(:depth) || 0
+ width = options.delete(:width) || 0
+ extra_columns = options.delete(:extra_columns)
+
+ ActiveRecord::Base.connection.create_table 'test_nodes' do |table|
+ table.string options[:ancestry_column] || :ancestry
+ table.integer options[:depth_cache_column] || :ancestry_depth if options[:cache_depth]
+ extra_columns.each do |name, type|
+ table.send type, name
+ end unless extra_columns.nil?
+ end
+
+ begin
+ model = Class.new(ActiveRecord::Base)
+ (class << model; self; end).send :define_method, :model_name do; Struct.new(:human, :underscore).new 'TestNode', 'test_node'; end
+ const_set 'TestNode', model
+
+ model.send :set_table_name, 'test_nodes'
+ model.has_ancestry options unless options.delete(:skip_ancestry)
+
+ if depth > 0
+ yield model, create_test_nodes(model, depth, width)
+ else
+ yield model
+ end
+ ensure
+ ActiveRecord::Base.connection.drop_table 'test_nodes'
+ remove_const "TestNode"
+ end
end
-
- def create_test_nodes model, parent, level, quantity
- unless level == 0
- (1..quantity).map do |i|
+
+ def self.create_test_nodes model, depth, width, parent = nil
+ unless depth == 0
+ Array.new width do
node = model.create!(:parent => parent)
- [node, create_test_nodes(model, node, level - 1, quantity)]
+ [node, create_test_nodes(model, depth - 1, width, node)]
end
else; []; end
end
+end
+AncestryTestDatabase.setup
+
+puts "\nRunning Ancestry test suite:"
+puts " Ruby: #{RUBY_VERSION}"
+#puts " ActiveRecord: #{ActiveRecord::VERSION::STRING}"
+puts " Database: #{ActiveRecord::Base.connection.adapter_name}\n\n"
+
+class HasAncestryTreeTest < ActiveSupport::TestCase
def test_default_ancestry_column
- assert_equal :ancestry, TestNode.ancestry_column
+ AncestryTestDatabase.with_model do |model|
+ assert_equal :ancestry, model.ancestry_column
+ end
end
def test_non_default_ancestry_column
- assert_equal :alternative_ancestry, AlternativeTestNode.ancestry_column
+ AncestryTestDatabase.with_model :ancestry_column => :alternative_ancestry do |model|
+ assert_equal :alternative_ancestry, model.ancestry_column
+ end
end
def test_setting_ancestry_column
- TestNode.ancestry_column = :ancestors
- assert_equal :ancestors, TestNode.ancestry_column
- TestNode.ancestry_column = :ancestry
- assert_equal :ancestry, TestNode.ancestry_column
+ AncestryTestDatabase.with_model do |model|
+ model.ancestry_column = :ancestors
+ assert_equal :ancestors, model.ancestry_column
+ model.ancestry_column = :ancestry
+ assert_equal :ancestry, model.ancestry_column
+ end
end
def test_default_orphan_strategy
- assert_equal :destroy, TestNode.orphan_strategy
+ AncestryTestDatabase.with_model do |model|
+ assert_equal :destroy, model.orphan_strategy
+ end
end
def test_non_default_orphan_strategy
- assert_equal :rootify, AlternativeTestNode.orphan_strategy
+ AncestryTestDatabase.with_model :orphan_strategy => :rootify do |model|
+ assert_equal :rootify, model.orphan_strategy
+ end
end
def test_setting_orphan_strategy
- TestNode.orphan_strategy = :rootify
- assert_equal :rootify, TestNode.orphan_strategy
- TestNode.orphan_strategy = :destroy
- assert_equal :destroy, TestNode.orphan_strategy
+ AncestryTestDatabase.with_model do |model|
+ model.orphan_strategy = :rootify
+ assert_equal :rootify, model.orphan_strategy
+ model.orphan_strategy = :destroy
+ assert_equal :destroy, model.orphan_strategy
+ end
end
-
+
def test_setting_invalid_orphan_strategy
- assert_raise Ancestry::AncestryException do
- TestNode.orphan_strategy = :non_existent_orphan_strategy
+ AncestryTestDatabase.with_model do |model|
+ assert_raise Ancestry::AncestryException do
+ model.orphan_strategy = :non_existent_orphan_strategy
+ end
end
end
-
+
def test_setup_test_nodes
- [TestNode, AlternativeTestNode, ActsAsTreeTestNode].each do |model|
- roots = setup_test_nodes model, 3, 3
+ AncestryTestDatabase.with_model :depth => 3, :width => 3 do |model, roots|
assert_equal Array, roots.class
assert_equal 3, roots.length
roots.each do |node, children|
@@ -98,341 +132,384 @@ def test_setup_test_nodes
end
end
end
-
+
def test_tree_navigation
- roots = setup_test_nodes TestNode, 3, 3
- roots.each do |lvl0_node, lvl0_children|
- # Ancestors assertions
- assert_equal [], lvl0_node.ancestor_ids
- assert_equal [], lvl0_node.ancestors
- assert_equal [lvl0_node.id], lvl0_node.path_ids
- assert_equal [lvl0_node], lvl0_node.path
- assert_equal 0, lvl0_node.depth
- # Parent assertions
- assert_equal nil, lvl0_node.parent_id
- assert_equal nil, lvl0_node.parent
- # Root assertions
- assert_equal lvl0_node.id, lvl0_node.root_id
- assert_equal lvl0_node, lvl0_node.root
- assert lvl0_node.is_root?
- # Children assertions
- assert_equal lvl0_children.map(&:first).map(&:id), lvl0_node.child_ids
- assert_equal lvl0_children.map(&:first), lvl0_node.children
- assert lvl0_node.has_children?
- assert !lvl0_node.is_childless?
- # Siblings assertions
- assert_equal roots.map(&:first).map(&:id), lvl0_node.sibling_ids
- assert_equal roots.map(&:first), lvl0_node.siblings
- assert lvl0_node.has_siblings?
- assert !lvl0_node.is_only_child?
- # Descendants assertions
- descendants = TestNode.all.find_all do |node|
- node.ancestor_ids.include? lvl0_node.id
- end
- assert_equal descendants.map(&:id), lvl0_node.descendant_ids
- assert_equal descendants, lvl0_node.descendants
- assert_equal [lvl0_node] + descendants, lvl0_node.subtree
-
- lvl0_children.each do |lvl1_node, lvl1_children|
+ AncestryTestDatabase.with_model :depth => 3, :width => 3 do |model, roots|
+ roots.each do |lvl0_node, lvl0_children|
# Ancestors assertions
- assert_equal [lvl0_node.id], lvl1_node.ancestor_ids
- assert_equal [lvl0_node], lvl1_node.ancestors
- assert_equal [lvl0_node.id, lvl1_node.id], lvl1_node.path_ids
- assert_equal [lvl0_node, lvl1_node], lvl1_node.path
- assert_equal 1, lvl1_node.depth
+ assert_equal [], lvl0_node.ancestor_ids
+ assert_equal [], lvl0_node.ancestors
+ assert_equal [lvl0_node.id], lvl0_node.path_ids
+ assert_equal [lvl0_node], lvl0_node.path
+ assert_equal 0, lvl0_node.depth
# Parent assertions
- assert_equal lvl0_node.id, lvl1_node.parent_id
- assert_equal lvl0_node, lvl1_node.parent
+ assert_equal nil, lvl0_node.parent_id
+ assert_equal nil, lvl0_node.parent
# Root assertions
- assert_equal lvl0_node.id, lvl1_node.root_id
- assert_equal lvl0_node, lvl1_node.root
- assert !lvl1_node.is_root?
+ assert_equal lvl0_node.id, lvl0_node.root_id
+ assert_equal lvl0_node, lvl0_node.root
+ assert lvl0_node.is_root?
# Children assertions
- assert_equal lvl1_children.map(&:first).map(&:id), lvl1_node.child_ids
- assert_equal lvl1_children.map(&:first), lvl1_node.children
- assert lvl1_node.has_children?
- assert !lvl1_node.is_childless?
+ assert_equal lvl0_children.map(&:first).map(&:id), lvl0_node.child_ids
+ assert_equal lvl0_children.map(&:first), lvl0_node.children
+ assert lvl0_node.has_children?
+ assert !lvl0_node.is_childless?
# Siblings assertions
- assert_equal lvl0_children.map(&:first).map(&:id), lvl1_node.sibling_ids
- assert_equal lvl0_children.map(&:first), lvl1_node.siblings
- assert lvl1_node.has_siblings?
- assert !lvl1_node.is_only_child?
+ assert_equal roots.map(&:first).map(&:id), lvl0_node.sibling_ids
+ assert_equal roots.map(&:first), lvl0_node.siblings
+ assert lvl0_node.has_siblings?
+ assert !lvl0_node.is_only_child?
# Descendants assertions
- descendants = TestNode.all.find_all do |node|
- node.ancestor_ids.include? lvl1_node.id
+ descendants = model.all.find_all do |node|
+ node.ancestor_ids.include? lvl0_node.id
end
- assert_equal descendants.map(&:id), lvl1_node.descendant_ids
- assert_equal descendants, lvl1_node.descendants
- assert_equal [lvl1_node] + descendants, lvl1_node.subtree
-
- lvl1_children.each do |lvl2_node, lvl2_children|
+ assert_equal descendants.map(&:id), lvl0_node.descendant_ids
+ assert_equal descendants, lvl0_node.descendants
+ assert_equal [lvl0_node] + descendants, lvl0_node.subtree
+
+ lvl0_children.each do |lvl1_node, lvl1_children|
# Ancestors assertions
- assert_equal [lvl0_node.id, lvl1_node.id], lvl2_node.ancestor_ids
- assert_equal [lvl0_node, lvl1_node], lvl2_node.ancestors
- assert_equal [lvl0_node.id, lvl1_node.id, lvl2_node.id], lvl2_node.path_ids
- assert_equal [lvl0_node, lvl1_node, lvl2_node], lvl2_node.path
- assert_equal 2, lvl2_node.depth
+ assert_equal [lvl0_node.id], lvl1_node.ancestor_ids
+ assert_equal [lvl0_node], lvl1_node.ancestors
+ assert_equal [lvl0_node.id, lvl1_node.id], lvl1_node.path_ids
+ assert_equal [lvl0_node, lvl1_node], lvl1_node.path
+ assert_equal 1, lvl1_node.depth
# Parent assertions
- assert_equal lvl1_node.id, lvl2_node.parent_id
- assert_equal lvl1_node, lvl2_node.parent
+ assert_equal lvl0_node.id, lvl1_node.parent_id
+ assert_equal lvl0_node, lvl1_node.parent
# Root assertions
- assert_equal lvl0_node.id, lvl2_node.root_id
- assert_equal lvl0_node, lvl2_node.root
- assert !lvl2_node.is_root?
+ assert_equal lvl0_node.id, lvl1_node.root_id
+ assert_equal lvl0_node, lvl1_node.root
+ assert !lvl1_node.is_root?
# Children assertions
- assert_equal [], lvl2_node.child_ids
- assert_equal [], lvl2_node.children
- assert !lvl2_node.has_children?
- assert lvl2_node.is_childless?
+ assert_equal lvl1_children.map(&:first).map(&:id), lvl1_node.child_ids
+ assert_equal lvl1_children.map(&:first), lvl1_node.children
+ assert lvl1_node.has_children?
+ assert !lvl1_node.is_childless?
# Siblings assertions
- assert_equal lvl1_children.map(&:first).map(&:id), lvl2_node.sibling_ids
- assert_equal lvl1_children.map(&:first), lvl2_node.siblings
- assert lvl2_node.has_siblings?
- assert !lvl2_node.is_only_child?
+ assert_equal lvl0_children.map(&:first).map(&:id), lvl1_node.sibling_ids
+ assert_equal lvl0_children.map(&:first), lvl1_node.siblings
+ assert lvl1_node.has_siblings?
+ assert !lvl1_node.is_only_child?
# Descendants assertions
- descendants = TestNode.all.find_all do |node|
- node.ancestor_ids.include? lvl2_node.id
+ descendants = model.all.find_all do |node|
+ node.ancestor_ids.include? lvl1_node.id
+ end
+ assert_equal descendants.map(&:id), lvl1_node.descendant_ids
+ assert_equal descendants, lvl1_node.descendants
+ assert_equal [lvl1_node] + descendants, lvl1_node.subtree
+
+ lvl1_children.each do |lvl2_node, lvl2_children|
+ # Ancestors assertions
+ assert_equal [lvl0_node.id, lvl1_node.id], lvl2_node.ancestor_ids
+ assert_equal [lvl0_node, lvl1_node], lvl2_node.ancestors
+ assert_equal [lvl0_node.id, lvl1_node.id, lvl2_node.id], lvl2_node.path_ids
+ assert_equal [lvl0_node, lvl1_node, lvl2_node], lvl2_node.path
+ assert_equal 2, lvl2_node.depth
+ # Parent assertions
+ assert_equal lvl1_node.id, lvl2_node.parent_id
+ assert_equal lvl1_node, lvl2_node.parent
+ # Root assertions
+ assert_equal lvl0_node.id, lvl2_node.root_id
+ assert_equal lvl0_node, lvl2_node.root
+ assert !lvl2_node.is_root?
+ # Children assertions
+ assert_equal [], lvl2_node.child_ids
+ assert_equal [], lvl2_node.children
+ assert !lvl2_node.has_children?
+ assert lvl2_node.is_childless?
+ # Siblings assertions
+ assert_equal lvl1_children.map(&:first).map(&:id), lvl2_node.sibling_ids
+ assert_equal lvl1_children.map(&:first), lvl2_node.siblings
+ assert lvl2_node.has_siblings?
+ assert !lvl2_node.is_only_child?
+ # Descendants assertions
+ descendants = model.all.find_all do |node|
+ node.ancestor_ids.include? lvl2_node.id
+ end
+ assert_equal descendants.map(&:id), lvl2_node.descendant_ids
+ assert_equal descendants, lvl2_node.descendants
+ assert_equal [lvl2_node] + descendants, lvl2_node.subtree
end
- assert_equal descendants.map(&:id), lvl2_node.descendant_ids
- assert_equal descendants, lvl2_node.descendants
- assert_equal [lvl2_node] + descendants, lvl2_node.subtree
end
end
end
end
-
- def test_named_scopes
- roots = setup_test_nodes TestNode, 3, 3
- # Roots assertion
- assert_equal roots.map(&:first), TestNode.roots.all
+ def test_scopes
+ AncestryTestDatabase.with_model :depth => 3, :width => 3 do |model, roots|
+ # Roots assertion
+ assert_equal roots.map(&:first), model.roots.all
- TestNode.all.each do |test_node|
- # Assertions for ancestors_of named scope
- assert_equal test_node.ancestors, TestNode.ancestors_of(test_node)
- assert_equal test_node.ancestors, TestNode.ancestors_of(test_node.id)
- # Assertions for children_of named scope
- assert_equal test_node.children, TestNode.children_of(test_node)
- assert_equal test_node.children, TestNode.children_of(test_node.id)
- # Assertions for descendants_of named scope
- assert_equal test_node.descendants, TestNode.descendants_of(test_node)
- assert_equal test_node.descendants, TestNode.descendants_of(test_node.id)
- # Assertions for subtree_of named scope
- assert_equal test_node.subtree, TestNode.subtree_of(test_node)
- assert_equal test_node.subtree, TestNode.subtree_of(test_node.id)
- # Assertions for siblings_of named scope
- assert_equal test_node.siblings, TestNode.siblings_of(test_node)
- assert_equal test_node.siblings, TestNode.siblings_of(test_node.id)
+ model.all.each do |test_node|
+ # Assertions for ancestors_of named scope
+ assert_equal test_node.ancestors.all, model.ancestors_of(test_node).all
+ assert_equal test_node.ancestors.all, model.ancestors_of(test_node.id).all
+ # Assertions for children_of named scope
+ assert_equal test_node.children.all, model.children_of(test_node).all
+ assert_equal test_node.children.all, model.children_of(test_node.id).all
+ # Assertions for descendants_of named scope
+ assert_equal test_node.descendants.all, model.descendants_of(test_node).all
+ assert_equal test_node.descendants.all, model.descendants_of(test_node.id).all
+ # Assertions for subtree_of named scope
+ assert_equal test_node.subtree.all, model.subtree_of(test_node).all
+ assert_equal test_node.subtree.all, model.subtree_of(test_node.id).all
+ # Assertions for siblings_of named scope
+ assert_equal test_node.siblings.all, model.siblings_of(test_node).all
+ assert_equal test_node.siblings.all, model.siblings_of(test_node.id).all
+ end
end
end
- def test_ancestroy_column_validation
- node = TestNode.create
- ['3', '10/2', '1/4/30', nil].each do |value|
- node.write_attribute TestNode.ancestry_column, value
- node.valid?; assert !node.errors.invalid?(TestNode.ancestry_column)
- end
- ['1/3/', '/2/3', 'a', 'a/b', '-34', '/54'].each do |value|
- node.write_attribute TestNode.ancestry_column, value
- node.valid?; assert node.errors.invalid?(TestNode.ancestry_column)
+ def test_ancestry_column_validation
+ AncestryTestDatabase.with_model do |model|
+ node = model.create
+ ['3', '10/2', '1/4/30', nil].each do |value|
+ node.send :write_attribute, model.ancestry_column, value
+ node.valid?; assert node.errors[model.ancestry_column].blank?
+ end
+ ['1/3/', '/2/3', 'a', 'a/b', '-34', '/54'].each do |value|
+ node.send :write_attribute, model.ancestry_column, value
+ node.valid?; assert !node.errors[model.ancestry_column].blank?
+ end
end
end
def test_descendants_move_with_node
- root1, root2, root3 = setup_test_nodes(TestNode, 3, 3).map(&:first)
- assert_no_difference 'root1.descendants.size' do
- assert_difference 'root2.descendants.size', root1.subtree.size do
- root1.parent = root2
- root1.save!
+ AncestryTestDatabase.with_model :depth => 3, :width => 3 do |model, roots|
+ root1, root2, root3 = roots.map(&:first)
+ assert_no_difference 'root1.descendants.size' do
+ assert_difference 'root2.descendants.size', root1.subtree.size do
+ root1.parent = root2
+ root1.save!
+ end
end
- end
- assert_no_difference 'root2.descendants.size' do
- assert_difference 'root3.descendants.size', root2.subtree.size do
- root2.parent = root3
- root2.save!
+ assert_no_difference 'root2.descendants.size' do
+ assert_difference 'root3.descendants.size', root2.subtree.size do
+ root2.parent = root3
+ root2.save!
+ end
end
- end
- assert_no_difference 'root1.descendants.size' do
- assert_difference 'root2.descendants.size', -root1.subtree.size do
- assert_difference 'root3.descendants.size', -root1.subtree.size do
- root1.parent = nil
- root1.save!
+ assert_no_difference 'root1.descendants.size' do
+ assert_difference 'root2.descendants.size', -root1.subtree.size do
+ assert_difference 'root3.descendants.size', -root1.subtree.size do
+ root1.parent = nil
+ root1.save!
+ end
end
end
end
end
def test_orphan_rootify_strategy
- TestNode.orphan_strategy = :rootify
- root = setup_test_nodes(TestNode, 3, 3).first.first
- children = root.children.all
- root.destroy
- children.each do |child|
- child.reload
- assert child.is_root?
- assert_equal 3, child.children.size
+ AncestryTestDatabase.with_model :depth => 3, :width => 3 do |model, roots|
+ model.orphan_strategy = :rootify
+ root = roots.first.first
+ children = root.children.all
+ root.destroy
+ children.each do |child|
+ child.reload
+ assert child.is_root?
+ assert_equal 3, child.children.size
+ end
end
end
-
+
def test_orphan_destroy_strategy
- TestNode.orphan_strategy = :destroy
- root = setup_test_nodes(TestNode, 3, 3).first.first
- assert_difference 'TestNode.count', -root.subtree.size do
- root.destroy
- end
- node = TestNode.roots.first.children.first
- assert_difference 'TestNode.count', -node.subtree.size do
- node.destroy
+ AncestryTestDatabase.with_model :depth => 3, :width => 3 do |model, roots|
+ model.orphan_strategy = :destroy
+ root = roots.first.first
+ assert_difference 'model.count', -root.subtree.size do
+ root.destroy
+ end
+ node = model.roots.first.children.first
+ assert_difference 'model.count', -node.subtree.size do
+ node.destroy
+ end
end
end
-
+
def test_orphan_restrict_strategy
- TestNode.orphan_strategy = :restrict
- setup_test_nodes(TestNode, 3, 3)
- root = TestNode.roots.first
- assert_raise Ancestry::AncestryException do
- root.destroy
- end
- assert_nothing_raised Ancestry::AncestryException do
- root.children.first.children.first.destroy
+ AncestryTestDatabase.with_model :depth => 3, :width => 3 do |model, roots|
+ model.orphan_strategy = :restrict
+ root = roots.first.first
+ assert_raise Ancestry::AncestryException do
+ root.destroy
+ end
+ assert_nothing_raised Ancestry::AncestryException do
+ root.children.first.children.first.destroy
+ end
end
-
end
def test_integrity_checking
- # Check that there are no errors on a valid data set
- setup_test_nodes(TestNode, 3, 3)
- assert_nothing_raised do
- TestNode.check_ancestry_integrity!
+ AncestryTestDatabase.with_model :width => 3, :depth => 3 do |model, roots|
+ # Check that there are no errors on a valid tree
+ assert_nothing_raised do
+ model.check_ancestry_integrity!
+ end
end
-
- # Check detection of invalid format for ancestry column
- setup_test_nodes(TestNode, 3, 3).first.first.update_attribute TestNode.ancestry_column, 'invalid_ancestry'
- assert_raise Ancestry::AncestryIntegrityException do
- TestNode.check_ancestry_integrity!
+
+ AncestryTestDatabase.with_model :width => 3, :depth => 3 do |model, roots|
+ # Check detection of invalid format for ancestry column
+ roots.first.first.update_attribute model.ancestry_column, 'invalid_ancestry'
+ assert_raise Ancestry::AncestryIntegrityException do
+ model.check_ancestry_integrity!
+ end
end
- # Check detection of non-existent ancestor
- setup_test_nodes(TestNode, 3, 3).first.first.update_attribute TestNode.ancestry_column, 35
- assert_raise Ancestry::AncestryIntegrityException do
- TestNode.check_ancestry_integrity!
+ AncestryTestDatabase.with_model :width => 3, :depth => 3 do |model, roots|
+ # Check detection of non-existent ancestor
+ roots.first.first.update_attribute model.ancestry_column, 35
+ assert_raise Ancestry::AncestryIntegrityException do
+ model.check_ancestry_integrity!
+ end
end
-
- # Check detection of cyclic ancestry
- node = setup_test_nodes(TestNode, 3, 3).first.first
- node.update_attribute TestNode.ancestry_column, node.id
- assert_raise Ancestry::AncestryIntegrityException do
- TestNode.check_ancestry_integrity!
+
+ AncestryTestDatabase.with_model :width => 3, :depth => 3 do |model, roots|
+ # Check detection of cyclic ancestry
+ node = roots.first.first
+ node.update_attribute model.ancestry_column, node.id
+ assert_raise Ancestry::AncestryIntegrityException do
+ model.check_ancestry_integrity!
+ end
end
-
- # Check detection of conflicting parent id
- TestNode.destroy_all
- TestNode.create!(TestNode.ancestry_column => TestNode.create!(TestNode.ancestry_column => TestNode.create!(TestNode.ancestry_column => nil).id).id)
- assert_raise Ancestry::AncestryIntegrityException do
- TestNode.check_ancestry_integrity!
+
+ AncestryTestDatabase.with_model do |model|
+ # Check detection of conflicting parent id
+ model.destroy_all
+ model.create!(model.ancestry_column => model.create!(model.ancestry_column => model.create!(model.ancestry_column => nil).id).id)
+ assert_raise Ancestry::AncestryIntegrityException do
+ model.check_ancestry_integrity!
+ end
end
end
-
- def assert_integrity_restoration
+
+ def assert_integrity_restoration model
assert_raise Ancestry::AncestryIntegrityException do
- TestNode.check_ancestry_integrity!
+ model.check_ancestry_integrity!
end
- TestNode.restore_ancestry_integrity!
+ model.restore_ancestry_integrity!
assert_nothing_raised do
- TestNode.check_ancestry_integrity!
+ model.check_ancestry_integrity!
end
end
-
+
def test_integrity_restoration
# Check that integrity is restored for invalid format for ancestry column
- setup_test_nodes(TestNode, 3, 3).first.first.update_attribute TestNode.ancestry_column, 'invalid_ancestry'
- assert_integrity_restoration
+ AncestryTestDatabase.with_model :width => 3, :depth => 3 do |model, roots|
+ roots.first.first.update_attribute model.ancestry_column, 'invalid_ancestry'
+ assert_integrity_restoration model
+ end
# Check that integrity is restored for non-existent ancestor
- setup_test_nodes(TestNode, 3, 3).first.first.update_attribute TestNode.ancestry_column, 35
- assert_integrity_restoration
-
+ AncestryTestDatabase.with_model :width => 3, :depth => 3 do |model, roots|
+ roots.first.first.update_attribute model.ancestry_column, 35
+ assert_integrity_restoration model
+ end
+
# Check that integrity is restored for cyclic ancestry
- node = setup_test_nodes(TestNode, 3, 3).first.first
- node.update_attribute TestNode.ancestry_column, node.id
- assert_integrity_restoration
-
+ AncestryTestDatabase.with_model :width => 3, :depth => 3 do |model, roots|
+ node = roots.first.first
+ node.update_attribute model.ancestry_column, node.id
+ assert_integrity_restoration model
+ end
+
# Check that integrity is restored for conflicting parent id
- TestNode.destroy_all
- TestNode.create!(TestNode.ancestry_column => TestNode.create!(TestNode.ancestry_column => TestNode.create!(TestNode.ancestry_column => nil).id).id)
- assert_integrity_restoration
+ AncestryTestDatabase.with_model do |model|
+ model.destroy_all
+ model.create!(model.ancestry_column => model.create!(model.ancestry_column => model.create!(model.ancestry_column => nil).id).id)
+ assert_integrity_restoration model
+ end
end
def test_arrangement
- id_sorter = Proc.new do |a, b|; a.id <=> b.id; end
- setup_test_nodes(TestNode, 3, 3)
- arranged_nodes = TestNode.arrange
- assert_equal 3, arranged_nodes.size
- arranged_nodes.each do |node, children|
- assert_equal node.children.sort(&id_sorter), children.keys.sort(&id_sorter)
- children.each do |node, children|
+ AncestryTestDatabase.with_model :depth => 3, :width => 3 do |model, roots|
+ id_sorter = Proc.new do |a, b|; a.id <=> b.id; end
+ arranged_nodes = model.arrange
+ assert_equal 3, arranged_nodes.size
+ arranged_nodes.each do |node, children|
assert_equal node.children.sort(&id_sorter), children.keys.sort(&id_sorter)
children.each do |node, children|
- assert_equal 0, children.size
+ assert_equal node.children.sort(&id_sorter), children.keys.sort(&id_sorter)
+ children.each do |node, children|
+ assert_equal 0, children.size
+ end
end
end
end
end
def test_node_creation_though_scope
- node = TestNode.create!
- child = node.children.create
- assert_equal node, child.parent
-
- other_child = child.siblings.create!
- assert_equal node, other_child.parent
-
- grandchild = TestNode.children_of(child).new
- grandchild.save
- assert_equal child, grandchild.parent
-
- other_grandchild = TestNode.siblings_of(grandchild).new
- other_grandchild.save!
- assert_equal child, other_grandchild.parent
+ AncestryTestDatabase.with_model do |model|
+ node = model.create!
+ child = node.children.create
+ assert_equal node, child.parent
+
+ other_child = child.siblings.create!
+ assert_equal node, other_child.parent
+
+ grandchild = model.children_of(child).new
+ grandchild.save
+ assert_equal child, grandchild.parent
+
+ other_grandchild = model.siblings_of(grandchild).new
+ other_grandchild.save!
+ assert_equal child, other_grandchild.parent
+ end
end
def test_validate_ancestry_exclude_self
- parent = TestNode.create!
- child = parent.children.create!
- assert_raise ActiveRecord::RecordInvalid do
- parent.update_attributes! :parent => child
+ AncestryTestDatabase.with_model do |model|
+ parent = model.create!
+ child = parent.children.create!
+ assert_raise ActiveRecord::RecordInvalid do
+ parent.update_attributes! :parent => child
+ end
end
end
def test_depth_caching
- roots = setup_test_nodes TestNode, 3, 3
- roots.each do |lvl0_node, lvl0_children|
- assert_equal 0, lvl0_node.depth_cache
- lvl0_children.each do |lvl1_node, lvl1_children|
- assert_equal 1, lvl1_node.depth_cache
- lvl1_children.each do |lvl2_node, lvl2_children|
- assert_equal 2, lvl2_node.depth_cache
+ AncestryTestDatabase.with_model :depth => 3, :width => 3, :cache_depth => true, :depth_cache_column => :depth_cache do |model, roots|
+ roots.each do |lvl0_node, lvl0_children|
+ assert_equal 0, lvl0_node.depth_cache
+ lvl0_children.each do |lvl1_node, lvl1_children|
+ assert_equal 1, lvl1_node.depth_cache
+ lvl1_children.each do |lvl2_node, lvl2_children|
+ assert_equal 2, lvl2_node.depth_cache
+ end
end
end
end
end
def test_depth_scopes
- setup_test_nodes TestNode, 4, 4
- TestNode.before_depth(2).all? { |node| assert node.depth < 2 }
- TestNode.to_depth(2).all? { |node| assert node.depth <= 2 }
- TestNode.at_depth(2).all? { |node| assert node.depth == 2 }
- TestNode.from_depth(2).all? { |node| assert node.depth >= 2 }
- TestNode.after_depth(2).all? { |node| assert node.depth > 2 }
+ AncestryTestDatabase.with_model :depth => 4, :width => 2, :cache_depth => true do |model, roots|
+ model.before_depth(2).all? { |node| assert node.depth < 2 }
+ model.to_depth(2).all? { |node| assert node.depth <= 2 }
+ model.at_depth(2).all? { |node| assert node.depth == 2 }
+ model.from_depth(2).all? { |node| assert node.depth >= 2 }
+ model.after_depth(2).all? { |node| assert node.depth > 2 }
+ end
end
def test_depth_scopes_unavailable
- assert_raise Ancestry::AncestryException do
- AlternativeTestNode.before_depth(1)
- AlternativeTestNode.to_depth(1)
- AlternativeTestNode.at_depth(1)
- AlternativeTestNode.from_depth(1)
- AlternativeTestNode.after_depth(1)
+ AncestryTestDatabase.with_model do |model|
+ assert_raise Ancestry::AncestryException do
+ model.before_depth(1)
+ end
+ assert_raise Ancestry::AncestryException do
+ model.to_depth(1)
+ end
+ assert_raise Ancestry::AncestryException do
+ model.at_depth(1)
+ end
+ assert_raise Ancestry::AncestryException do
+ model.from_depth(1)
+ end
+ assert_raise Ancestry::AncestryException do
+ model.after_depth(1)
+ end
end
end
@@ -446,145 +523,165 @@ def test_invalid_has_ancestry_options
end
def test_build_ancestry_from_parent_ids
- [ParentIdTestNode.create!].each do |parent|
- (Array.new(5) { ParentIdTestNode.create! :parent_id => parent.id }).each do |parent|
- (Array.new(5) { ParentIdTestNode.create! :parent_id => parent.id }).each do |parent|
- (Array.new(5) { ParentIdTestNode.create! :parent_id => parent.id })
+ AncestryTestDatabase.with_model :skip_ancestry => true, :extra_columns => {:parent_id => :integer} do |model|
+ [model.create!].each do |parent|
+ (Array.new(5) { model.create! :parent_id => parent.id }).each do |parent|
+ (Array.new(5) { model.create! :parent_id => parent.id }).each do |parent|
+ (Array.new(5) { model.create! :parent_id => parent.id })
+ end
end
end
- end
- # Assert all nodes where created
- assert_equal 156, ParentIdTestNode.count
-
- ParentIdTestNode.has_ancestry
- ParentIdTestNode.build_ancestry_from_parent_ids!
-
- # Assert ancestry integirty
- assert_nothing_raised do
- ParentIdTestNode.check_ancestry_integrity!
- end
-
- roots = ParentIdTestNode.roots.all
- # Assert single root node
- assert_equal 1, roots.size
-
- # Assert it has 5 children
- roots.each do |parent|
- assert 5, parent.children.count
- parent.children.each do |parent|
+ # Assert all nodes where created
+ assert_equal 156, model.count
+
+ model.has_ancestry
+ model.build_ancestry_from_parent_ids!
+
+ # Assert ancestry integrity
+ assert_nothing_raised do
+ model.check_ancestry_integrity!
+ end
+
+ roots = model.roots.all
+ # Assert single root node
+ assert_equal 1, roots.size
+
+ # Assert it has 5 children
+ roots.each do |parent|
assert 5, parent.children.count
parent.children.each do |parent|
assert 5, parent.children.count
parent.children.each do |parent|
- assert 0, parent.children.count
+ assert 5, parent.children.count
+ parent.children.each do |parent|
+ assert 0, parent.children.count
+ end
end
end
end
end
end
def test_rebuild_depth_cache
- setup_test_nodes TestNode, 3, 3
- TestNode.connection.execute("update test_nodes set depth_cache = null;")
+ AncestryTestDatabase.with_model :depth => 3, :width => 3, :cache_depth => true, :depth_cache_column => :depth_cache do |model, roots|
+ model.connection.execute("update test_nodes set depth_cache = null;")
- # Assert cache was emptied correctly
- TestNode.all.each do |test_node|
- assert_equal nil, test_node.depth_cache
- end
+ # Assert cache was emptied correctly
+ model.all.each do |test_node|
+ assert_equal nil, test_node.depth_cache
+ end
- # Rebuild cache
- TestNode.rebuild_depth_cache!
+ # Rebuild cache
+ model.rebuild_depth_cache!
- # Assert cache was rebuild correctly
- TestNode.all.each do |test_node|
- assert_equal test_node.depth, test_node.depth_cache
+ # Assert cache was rebuild correctly
+ model.all.each do |test_node|
+ assert_equal test_node.depth, test_node.depth_cache
+ end
end
end
def test_exception_when_rebuilding_depth_cache_for_model_without_depth_caching
- assert_raise Ancestry::AncestryException do
- AlternativeTestNode.rebuild_depth_cache!
+ AncestryTestDatabase.with_model do |model|
+ assert_raise Ancestry::AncestryException do
+ model.rebuild_depth_cache!
+ end
end
end
def test_descendants_with_depth_constraints
- setup_test_nodes TestNode, 4, 4
-
- assert_equal 4, TestNode.roots.first.descendants(:before_depth => 2).count
- assert_equal 20, TestNode.roots.first.descendants(:to_depth => 2).count
- assert_equal 16, TestNode.roots.first.descendants(:at_depth => 2).count
- assert_equal 80, TestNode.roots.first.descendants(:from_depth => 2).count
- assert_equal 64, TestNode.roots.first.descendants(:after_depth => 2).count
+ AncestryTestDatabase.with_model :depth => 4, :width => 4, :cache_depth => true do |model, roots|
+ assert_equal 4, model.roots.first.descendants(:before_depth => 2).count
+ assert_equal 20, model.roots.first.descendants(:to_depth => 2).count
+ assert_equal 16, model.roots.first.descendants(:at_depth => 2).count
+ assert_equal 80, model.roots.first.descendants(:from_depth => 2).count
+ assert_equal 64, model.roots.first.descendants(:after_depth => 2).count
+ end
end
-
+
def test_subtree_with_depth_constraints
- setup_test_nodes TestNode, 4, 4
-
- assert_equal 5, TestNode.roots.first.subtree(:before_depth => 2).count
- assert_equal 21, TestNode.roots.first.subtree(:to_depth => 2).count
- assert_equal 16, TestNode.roots.first.subtree(:at_depth => 2).count
- assert_equal 80, TestNode.roots.first.subtree(:from_depth => 2).count
- assert_equal 64, TestNode.roots.first.subtree(:after_depth => 2).count
+ AncestryTestDatabase.with_model :depth => 4, :width => 4, :cache_depth => true do |model, roots|
+ assert_equal 5, model.roots.first.subtree(:before_depth => 2).count
+ assert_equal 21, model.roots.first.subtree(:to_depth => 2).count
+ assert_equal 16, model.roots.first.subtree(:at_depth => 2).count
+ assert_equal 80, model.roots.first.subtree(:from_depth => 2).count
+ assert_equal 64, model.roots.first.subtree(:after_depth => 2).count
+ end
end
-
-
+
+
def test_ancestors_with_depth_constraints
- node1 = TestNode.create!
- node2 = node1.children.create!
- node3 = node2.children.create!
- node4 = node3.children.create!
- node5 = node4.children.create!
- leaf = node5.children.create!
-
- assert_equal [node1, node2, node3], leaf.ancestors(:before_depth => -2)
- assert_equal [node1, node2, node3, node4], leaf.ancestors(:to_depth => -2)
- assert_equal [node4], leaf.ancestors(:at_depth => -2)
- assert_equal [node4, node5], leaf.ancestors(:from_depth => -2)
- assert_equal [node5], leaf.ancestors(:after_depth => -2)
+ AncestryTestDatabase.with_model :cache_depth => true do |model|
+ node1 = model.create!
+ node2 = node1.children.create!
+ node3 = node2.children.create!
+ node4 = node3.children.create!
+ node5 = node4.children.create!
+ leaf = node5.children.create!
+
+ assert_equal [node1, node2, node3], leaf.ancestors(:before_depth => -2)
+ assert_equal [node1, node2, node3, node4], leaf.ancestors(:to_depth => -2)
+ assert_equal [node4], leaf.ancestors(:at_depth => -2)
+ assert_equal [node4, node5], leaf.ancestors(:from_depth => -2)
+ assert_equal [node5], leaf.ancestors(:after_depth => -2)
+ end
end
-
+
def test_path_with_depth_constraints
- node1 = TestNode.create!
- node2 = node1.children.create!
- node3 = node2.children.create!
- node4 = node3.children.create!
- node5 = node4.children.create!
- leaf = node5.children.create!
-
- assert_equal [node1, node2, node3], leaf.path(:before_depth => -2)
- assert_equal [node1, node2, node3, node4], leaf.path(:to_depth => -2)
- assert_equal [node4], leaf.path(:at_depth => -2)
- assert_equal [node4, node5, leaf], leaf.path(:from_depth => -2)
- assert_equal [node5, leaf], leaf.path(:after_depth => -2)
+ AncestryTestDatabase.with_model :cache_depth => true do |model|
+ node1 = model.create!
+ node2 = node1.children.create!
+ node3 = node2.children.create!
+ node4 = node3.children.create!
+ node5 = node4.children.create!
+ leaf = node5.children.create!
+
+ assert_equal [node1, node2, node3], leaf.path(:before_depth => -2)
+ assert_equal [node1, node2, node3, node4], leaf.path(:to_depth => -2)
+ assert_equal [node4], leaf.path(:at_depth => -2)
+ assert_equal [node4, node5, leaf], leaf.path(:from_depth => -2)
+ assert_equal [node5, leaf], leaf.path(:after_depth => -2)
+ end
end
def test_exception_on_unknown_depth_column
- assert_raise Ancestry::AncestryException do
- TestNode.create!.subtree(:this_is_not_a_valid_depth_option => 42)
+ AncestryTestDatabase.with_model :cache_depth => true do |model|
+ assert_raise Ancestry::AncestryException do
+ model.create!.subtree(:this_is_not_a_valid_depth_option => 42)
+ end
end
end
def test_sti_support
- node1 = TestNodeSub1.create!
- node2 = TestNodeSub2.create! :parent => node1
- node3 = TestNodeSub1.create! :parent => node2
- node4 = TestNodeSub2.create! :parent => node3
- node5 = TestNodeSub1.create! :parent => node4
-
- assert_equal [node2, node3, node4, node5], node1.descendants
- assert_equal [node1, node2, node3, node4, node5], node1.subtree
- assert_equal [node1, node2, node3, node4], node5.ancestors
- assert_equal [node1, node2, node3, node4, node5], node5.path
+ AncestryTestDatabase.with_model :extra_columns => {:type => :string} do |model|
+ subclass1 = Object.const_set 'Subclass1', Class.new(model)
+ (class << subclass1; self; end).send :define_method, :model_name do; Struct.new(:human, :underscore).new 'Subclass1', 'subclass1'; end
+ subclass2 = Object.const_set 'Subclass2', Class.new(model)
+ (class << subclass2; self; end).send :define_method, :model_name do; Struct.new(:human, :underscore).new 'Subclass1', 'subclass1'; end
+
+ node1 = subclass1.create!
+ node2 = subclass2.create! :parent => node1
+ node3 = subclass1.create! :parent => node2
+ node4 = subclass2.create! :parent => node3
+ node5 = subclass1.create! :parent => node4
+
+ model.all.each do |node|
+ assert [subclass1, subclass2].include?(node.class)
+ end
+
+ assert_equal [node2.id, node3.id, node4.id, node5.id], node1.descendants.map(&:id)
+ assert_equal [node1.id, node2.id, node3.id, node4.id, node5.id], node1.subtree.map(&:id)
+ assert_equal [node1.id, node2.id, node3.id, node4.id], node5.ancestors.map(&:id)
+ assert_equal [node1.id, node2.id, node3.id, node4.id, node5.id], node5.path.map(&:id)
+ end
end
def test_arrange_order_option
- # In Ruby versions before 1.9 hashes aren't ordered so this doesn't make sense
- unless RUBY_VERSION =~ /^1\.8/
- roots = setup_test_nodes TestNode, 3, 3
- descending_nodes_lvl0 = TestNode.arrange :order => 'id desc'
- ascending_nodes_lvl0 = TestNode.arrange :order => 'id asc'
-
+ AncestryTestDatabase.with_model :width => 3, :depth => 3 do |model, roots|
+ descending_nodes_lvl0 = model.arrange :order => 'id desc'
+ ascending_nodes_lvl0 = model.arrange :order => 'id asc'
+
descending_nodes_lvl0.keys.zip(ascending_nodes_lvl0.keys.reverse).each do |descending_node, ascending_node|
assert_equal descending_node, ascending_node
descending_nodes_lvl1 = descending_nodes_lvl0[descending_node]
View
24 test/schema.rb
@@ -1,24 +0,0 @@
-ActiveRecord::Schema.define(:version => 0) do
- create_table :test_nodes, :force => true do |t|
- t.string :ancestry
- t.integer :depth_cache
- t.string :type
- end
-
- create_table :alternative_test_nodes, :force => true do |t|
- t.string :alternative_ancestry
- end
-
- create_table :other_test_nodes, :force => true do |t|
- t.string :ancestry
- end
-
- create_table :parent_id_test_nodes, :force => true do |t|
- t.string :ancestry
- t.integer :parent_id
- end
-
- create_table :acts_as_tree_test_nodes, :force => true do |t|
- t.string :ancestry
- end
-end
View
31 test/test_helper.rb
@@ -1,31 +0,0 @@
-ENV['RAILS_ENV'] = 'test'
-ENV['RAILS_ROOT'] ||= File.dirname(__FILE__) + '/../../../..'
-
-require 'test/unit'
-require File.expand_path(File.join(ENV['RAILS_ROOT'], 'config/environment.rb'))
-require 'test_help'
-
-def load_schema
- config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
- ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
- db_adapter = ENV['DB']
- # no db passed, try one of these fine config-free DBs before bombing.
- db_adapter ||= begin
- require 'rubygems'
- require 'sqlite'
- 'sqlite'
- rescue MissingSourceFile
- begin
- require 'sqlite3'
- 'sqlite3'
- rescue MissingSourceFile
- end
- end
-
- if db_adapter.nil?
- raise "No DB Adapter selected. Pass the DB= option to pick one, or install Sqlite or Sqlite3."
- end
- ActiveRecord::Base.establish_connection(config[db_adapter])
- load(File.dirname(__FILE__) + "/schema.rb")
- require File.dirname(__FILE__) + '/../init.rb'
-end

0 comments on commit f1955bb

Please sign in to comment.