Permalink
Browse files

Refactored test suite to use appraisals and live in multiple test files

  • Loading branch information...
1 parent a5fdee9 commit 5f373b59ccf1a2a8973ab2984b0a2fb5378c2621 Stefan Kroes committed Dec 11, 2013
Showing with 1,826 additions and 1,037 deletions.
  1. +8 −0 Appraisals
  2. +3 −15 Gemfile
  3. +0 −17 Gemfile.rails-3-0
  4. +0 −17 Gemfile.rails-3-1
  5. +0 −17 Gemfile.rails-4-0
  6. +0 −51 Gemfile.rails-4-0.lock
  7. +0 −12 Rakefile
  8. +9 −0 gemfiles/mysql2_ar_3.0.20.gemfile
  9. +44 −0 gemfiles/mysql2_ar_3.0.20.gemfile.lock
  10. +9 −0 gemfiles/mysql2_ar_3.1.12.gemfile
  11. +46 −0 gemfiles/mysql2_ar_3.1.12.gemfile.lock
  12. +9 −0 gemfiles/mysql2_ar_3.2.14.gemfile
  13. +46 −0 gemfiles/mysql2_ar_3.2.14.gemfile.lock
  14. +9 −0 gemfiles/mysql2_ar_4.0.1.gemfile
  15. +54 −0 gemfiles/mysql2_ar_4.0.1.gemfile.lock
  16. +9 −0 gemfiles/mysql_ar_3.0.20.gemfile
  17. +13 −10 Gemfile.rails-3-0.lock → gemfiles/mysql_ar_3.0.20.gemfile.lock
  18. +9 −0 gemfiles/mysql_ar_3.1.12.gemfile
  19. +15 −12 Gemfile.rails-3-1.lock → gemfiles/mysql_ar_3.1.12.gemfile.lock
  20. +9 −0 gemfiles/mysql_ar_3.2.14.gemfile
  21. +46 −0 gemfiles/mysql_ar_3.2.14.gemfile.lock
  22. +9 −0 gemfiles/mysql_ar_4.0.1.gemfile
  23. +54 −0 gemfiles/mysql_ar_4.0.1.gemfile.lock
  24. +9 −0 gemfiles/pg_ar_3.0.20.gemfile
  25. +44 −0 gemfiles/pg_ar_3.0.20.gemfile.lock
  26. +9 −0 gemfiles/pg_ar_3.1.12.gemfile
  27. +46 −0 gemfiles/pg_ar_3.1.12.gemfile.lock
  28. +9 −0 gemfiles/pg_ar_3.2.14.gemfile
  29. +46 −0 gemfiles/pg_ar_3.2.14.gemfile.lock
  30. +9 −0 gemfiles/pg_ar_4.0.1.gemfile
  31. +54 −0 gemfiles/pg_ar_4.0.1.gemfile.lock
  32. +9 −0 gemfiles/postgresql_ar_3.0.20.gemfile
  33. +9 −0 gemfiles/postgresql_ar_3.1.12.gemfile
  34. +9 −0 gemfiles/postgresql_ar_3.2.14.gemfile
  35. +9 −0 gemfiles/postgresql_ar_4.0.1.gemfile
  36. +9 −0 gemfiles/sqlite3_ar_3.0.20.gemfile
  37. +44 −0 gemfiles/sqlite3_ar_3.0.20.gemfile.lock
  38. +9 −0 gemfiles/sqlite3_ar_3.1.12.gemfile
  39. +46 −0 gemfiles/sqlite3_ar_3.1.12.gemfile.lock
  40. +9 −0 gemfiles/sqlite3_ar_3.2.14.gemfile
  41. +46 −0 gemfiles/sqlite3_ar_3.2.14.gemfile.lock
  42. +9 −0 gemfiles/sqlite3_ar_4.0.1.gemfile
  43. +54 −0 gemfiles/sqlite3_ar_4.0.1.gemfile.lock
  44. +4 −4 lib/ancestry.rb
  45. +2 −2 lib/ancestry/instance_methods.rb
  46. +80 −0 test/concerns/arrangement_test.rb
  47. +44 −0 test/concerns/build_ancestry_test.rb
  48. +56 −0 test/concerns/default_scopes_test.rb
  49. +93 −0 test/concerns/depth_caching_test.rb
  50. +58 −0 test/concerns/depth_constraints_test.rb
  51. +81 −0 test/concerns/has_ancestry_test.rb
  52. +92 −0 test/concerns/integrity_checking_and_restoration_test.rb
  53. +90 −0 test/concerns/orphan_strategies_test.rb
  54. +69 −0 test/concerns/scopes_test.rb
  55. +30 −0 test/concerns/sort_by_ancestry_test.rb
  56. +37 −0 test/concerns/sti_support_test.rb
  57. +47 −0 test/concerns/touching_test.rb
  58. +109 −0 test/concerns/tree_navigration_test.rb
  59. +27 −0 test/concerns/validations_test.rb
  60. +18 −7 test/environment.rb
  61. +0 −873 test/has_ancestry_test.rb
View
8 Appraisals
@@ -0,0 +1,8 @@
+%w(3.0.20 3.1.12 3.2.14 4.0.1).each do |ar_versions|
+ %w(sqlite3 pg mysql).each do |db_type|
+ appraise "#{db_type}-ar-#{ar_versions}" do
+ gem 'activerecord', ar_versions
+ gem db_type
+ end
+ end
+end
View
18 Gemfile
@@ -1,17 +1,5 @@
source 'https://rubygems.org'
-gem 'activerecord', '~> 3.2.13'
-
-group :development, :test do
- gem 'debugger'
-end
-
-group :development do
- gem 'rdoc'
-end
-
-group :test do
- gem 'sqlite3'
- gem 'pg'
- gem 'mysql'
-end
+gem 'appraisal', '1.0.0.beta2'
+gem 'debugger'
+gem 'rdoc'
View
17 Gemfile.rails-3-0
@@ -1,17 +0,0 @@
-source 'https://rubygems.org'
-
-gem 'activerecord', '~> 3.0.20'
-
-group :development, :test do
- gem 'debugger'
-end
-
-group :development do
- gem 'rdoc'
-end
-
-group :test do
- gem 'sqlite3'
- gem 'pg'
- gem 'mysql'
-end
View
17 Gemfile.rails-3-1
@@ -1,17 +0,0 @@
-source 'https://rubygems.org'
-
-gem 'activerecord', '~> 3.1.12'
-
-group :development, :test do
- gem 'debugger'
-end
-
-group :development do
- gem 'rdoc'
-end
-
-group :test do
- gem 'sqlite3'
- gem 'pg'
- gem 'mysql'
-end
View
17 Gemfile.rails-4-0
@@ -1,17 +0,0 @@
-source 'https://rubygems.org'
-
-gem 'activerecord', '~> 4.0.0.beta1'
-
-group :development, :test do
- gem 'debugger'
-end
-
-group :development do
- gem 'rdoc'
-end
-
-group :test do
- gem 'sqlite3'
- gem 'pg'
- gem 'mysql'
-end
View
51 Gemfile.rails-4-0.lock
@@ -1,51 +0,0 @@
-GEM
- remote: https://rubygems.org/
- specs:
- activemodel (4.0.0.beta1)
- activesupport (= 4.0.0.beta1)
- builder (~> 3.1.0)
- activerecord (4.0.0.beta1)
- activemodel (= 4.0.0.beta1)
- activerecord-deprecated_finders (~> 0.0.3)
- activesupport (= 4.0.0.beta1)
- arel (~> 4.0.0.beta1)
- activerecord-deprecated_finders (0.0.3)
- activesupport (4.0.0.beta1)
- i18n (~> 0.6.2)
- minitest (~> 4.2)
- multi_json (~> 1.3)
- thread_safe (~> 0.1)
- tzinfo (~> 0.3.33)
- arel (4.0.0.beta2)
- atomic (1.1.6)
- builder (3.1.4)
- columnize (0.3.6)
- debugger (1.5.0)
- columnize (>= 0.3.1)
- debugger-linecache (~> 1.2.0)
- debugger-ruby_core_source (~> 1.2.0)
- debugger-linecache (1.2.0)
- debugger-ruby_core_source (1.2.0)
- i18n (0.6.4)
- json (1.7.7)
- minitest (4.7.0)
- multi_json (1.7.2)
- mysql (2.9.1)
- pg (0.15.1)
- rdoc (4.0.1)
- json (~> 1.4)
- sqlite3 (1.3.7)
- thread_safe (0.1.0)
- atomic
- tzinfo (0.3.37)
-
-PLATFORMS
- ruby
-
-DEPENDENCIES
- activerecord (~> 4.0.0.beta1)
- debugger
- mysql
- pg
- rdoc
- sqlite3
View
12 Rakefile
@@ -13,18 +13,6 @@ Rake::TestTask.new(:test) do |t|
t.verbose = true
end
-desc 'Test the ancestry plugin with multiple databases and activerecord versions.'
-task :test_all do |t|
- commands = []
- %w(Gemfile.rails-3-0 Gemfile.rails-3-1 Gemfile Gemfile.rails-4-0).each do |gemfile|
- %w(sqlite3 postgresql mysql).each do |database_adapter|
- commands << "rake test db=#{database_adapter} BUNDLE_GEMFILE=#{gemfile}"
- end
- end
-
- exec commands.join(' && ')
-end
-
desc 'Generate documentation for the ancestry plugin.'
Rake::RDocTask.new(:rdoc) do |rdoc|
rdoc.rdoc_dir = 'doc'
View
9 gemfiles/mysql2_ar_3.0.20.gemfile
@@ -0,0 +1,9 @@
+# This file was generated by Appraisal
+
+source "https://rubygems.org"
+
+gem "appraisal", "1.0.0.beta2"
+gem "debugger"
+gem "rdoc"
+gem "activerecord", "3.0.20"
+gem "mysql2"
View
44 gemfiles/mysql2_ar_3.0.20.gemfile.lock
@@ -0,0 +1,44 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ activemodel (3.0.20)
+ activesupport (= 3.0.20)
+ builder (~> 2.1.2)
+ i18n (~> 0.5.0)
+ activerecord (3.0.20)
+ activemodel (= 3.0.20)
+ activesupport (= 3.0.20)
+ arel (~> 2.0.10)
+ tzinfo (~> 0.3.23)
+ activesupport (3.0.20)
+ appraisal (1.0.0.beta2)
+ bundler
+ rake
+ thor (>= 0.14.0)
+ arel (2.0.10)
+ builder (2.1.2)
+ columnize (0.3.6)
+ debugger (1.6.3)
+ columnize (>= 0.3.1)
+ debugger-linecache (~> 1.2.0)
+ debugger-ruby_core_source (~> 1.2.4)
+ debugger-linecache (1.2.0)
+ debugger-ruby_core_source (1.2.4)
+ i18n (0.5.0)
+ json (1.8.1)
+ mysql2 (0.3.14)
+ rake (10.1.0)
+ rdoc (4.0.1)
+ json (~> 1.4)
+ thor (0.18.1)
+ tzinfo (0.3.38)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ activerecord (= 3.0.20)
+ appraisal (= 1.0.0.beta2)
+ debugger
+ mysql2
+ rdoc
View
9 gemfiles/mysql2_ar_3.1.12.gemfile
@@ -0,0 +1,9 @@
+# This file was generated by Appraisal
+
+source "https://rubygems.org"
+
+gem "appraisal", "1.0.0.beta2"
+gem "debugger"
+gem "rdoc"
+gem "activerecord", "3.1.12"
+gem "mysql2"
View
46 gemfiles/mysql2_ar_3.1.12.gemfile.lock
@@ -0,0 +1,46 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ activemodel (3.1.12)
+ activesupport (= 3.1.12)
+ builder (~> 3.0.0)
+ i18n (~> 0.6)
+ activerecord (3.1.12)
+ activemodel (= 3.1.12)
+ activesupport (= 3.1.12)
+ arel (~> 2.2.3)
+ tzinfo (~> 0.3.29)
+ activesupport (3.1.12)
+ multi_json (~> 1.0)
+ appraisal (1.0.0.beta2)
+ bundler
+ rake
+ thor (>= 0.14.0)
+ arel (2.2.3)
+ builder (3.0.4)
+ columnize (0.3.6)
+ debugger (1.6.3)
+ columnize (>= 0.3.1)
+ debugger-linecache (~> 1.2.0)
+ debugger-ruby_core_source (~> 1.2.4)
+ debugger-linecache (1.2.0)
+ debugger-ruby_core_source (1.2.4)
+ i18n (0.6.9)
+ json (1.8.1)
+ multi_json (1.8.2)
+ mysql2 (0.3.14)
+ rake (10.1.0)
+ rdoc (4.0.1)
+ json (~> 1.4)
+ thor (0.18.1)
+ tzinfo (0.3.38)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ activerecord (= 3.1.12)
+ appraisal (= 1.0.0.beta2)
+ debugger
+ mysql2
+ rdoc
View
9 gemfiles/mysql2_ar_3.2.14.gemfile
@@ -0,0 +1,9 @@
+# This file was generated by Appraisal
+
+source "https://rubygems.org"
+
+gem "appraisal", "1.0.0.beta2"
+gem "debugger"
+gem "rdoc"
+gem "activerecord", "3.2.14"
+gem "mysql2"
View
46 gemfiles/mysql2_ar_3.2.14.gemfile.lock
@@ -0,0 +1,46 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ activemodel (3.2.14)
+ activesupport (= 3.2.14)
+ builder (~> 3.0.0)
+ activerecord (3.2.14)
+ activemodel (= 3.2.14)
+ activesupport (= 3.2.14)
+ arel (~> 3.0.2)
+ tzinfo (~> 0.3.29)
+ activesupport (3.2.14)
+ i18n (~> 0.6, >= 0.6.4)
+ multi_json (~> 1.0)
+ appraisal (1.0.0.beta2)
+ bundler
+ rake
+ thor (>= 0.14.0)
+ arel (3.0.3)
+ builder (3.0.4)
+ columnize (0.3.6)
+ debugger (1.6.3)
+ columnize (>= 0.3.1)
+ debugger-linecache (~> 1.2.0)
+ debugger-ruby_core_source (~> 1.2.4)
+ debugger-linecache (1.2.0)
+ debugger-ruby_core_source (1.2.4)
+ i18n (0.6.9)
+ json (1.8.1)
+ multi_json (1.8.2)
+ mysql2 (0.3.14)
+ rake (10.1.0)
+ rdoc (4.0.1)
+ json (~> 1.4)
+ thor (0.18.1)
+ tzinfo (0.3.38)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ activerecord (= 3.2.14)
+ appraisal (= 1.0.0.beta2)
+ debugger
+ mysql2
+ rdoc
View
9 gemfiles/mysql2_ar_4.0.1.gemfile
@@ -0,0 +1,9 @@
+# This file was generated by Appraisal
+
+source "https://rubygems.org"
+
+gem "appraisal", "1.0.0.beta2"
+gem "debugger"
+gem "rdoc"
+gem "activerecord", "4.0.1"
+gem "mysql2"
View
54 gemfiles/mysql2_ar_4.0.1.gemfile.lock
@@ -0,0 +1,54 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ activemodel (4.0.1)
+ activesupport (= 4.0.1)
+ builder (~> 3.1.0)
+ activerecord (4.0.1)
+ activemodel (= 4.0.1)
+ activerecord-deprecated_finders (~> 1.0.2)
+ activesupport (= 4.0.1)
+ arel (~> 4.0.0)
+ activerecord-deprecated_finders (1.0.3)
+ activesupport (4.0.1)
+ i18n (~> 0.6, >= 0.6.4)
+ minitest (~> 4.2)
+ multi_json (~> 1.3)
+ thread_safe (~> 0.1)
+ tzinfo (~> 0.3.37)
+ appraisal (1.0.0.beta2)
+ bundler
+ rake
+ thor (>= 0.14.0)
+ arel (4.0.1)
+ atomic (1.1.14)
+ builder (3.1.4)
+ columnize (0.3.6)
+ debugger (1.6.3)
+ columnize (>= 0.3.1)
+ debugger-linecache (~> 1.2.0)
+ debugger-ruby_core_source (~> 1.2.4)
+ debugger-linecache (1.2.0)
+ debugger-ruby_core_source (1.2.4)
+ i18n (0.6.9)
+ json (1.8.1)
+ minitest (4.7.5)
+ multi_json (1.8.2)
+ mysql2 (0.3.14)
+ rake (10.1.0)
+ rdoc (4.0.1)
+ json (~> 1.4)
+ thor (0.18.1)
+ thread_safe (0.1.3)
+ atomic
+ tzinfo (0.3.38)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ activerecord (= 4.0.1)
+ appraisal (= 1.0.0.beta2)
+ debugger
+ mysql2
+ rdoc
View
9 gemfiles/mysql_ar_3.0.20.gemfile
@@ -0,0 +1,9 @@
+# This file was generated by Appraisal
+
+source "https://rubygems.org"
+
+gem "appraisal", "1.0.0.beta2"
+gem "debugger"
+gem "rdoc"
+gem "activerecord", "3.0.20"
+gem "mysql"
View
23 Gemfile.rails-3-0.lock → gemfiles/mysql_ar_3.0.20.gemfile.lock
@@ -11,31 +11,34 @@ GEM
arel (~> 2.0.10)
tzinfo (~> 0.3.23)
activesupport (3.0.20)
+ appraisal (1.0.0.beta2)
+ bundler
+ rake
+ thor (>= 0.14.0)
arel (2.0.10)
builder (2.1.2)
columnize (0.3.6)
- debugger (1.5.0)
+ debugger (1.6.2)
columnize (>= 0.3.1)
debugger-linecache (~> 1.2.0)
- debugger-ruby_core_source (~> 1.2.0)
+ debugger-ruby_core_source (~> 1.2.3)
debugger-linecache (1.2.0)
- debugger-ruby_core_source (1.2.0)
+ debugger-ruby_core_source (1.2.3)
i18n (0.5.0)
- json (1.7.7)
+ json (1.8.1)
mysql (2.9.1)
- pg (0.15.0)
+ rake (10.1.0)
rdoc (4.0.1)
json (~> 1.4)
- sqlite3 (1.3.7)
- tzinfo (0.3.37)
+ thor (0.18.1)
+ tzinfo (0.3.38)
PLATFORMS
ruby
DEPENDENCIES
- activerecord (~> 3.0.20)
+ activerecord (= 3.0.20)
+ appraisal (= 1.0.0.beta2)
debugger
mysql
- pg
rdoc
- sqlite3
View
9 gemfiles/mysql_ar_3.1.12.gemfile
@@ -0,0 +1,9 @@
+# This file was generated by Appraisal
+
+source "https://rubygems.org"
+
+gem "appraisal", "1.0.0.beta2"
+gem "debugger"
+gem "rdoc"
+gem "activerecord", "3.1.12"
+gem "mysql"
View
27 Gemfile.rails-3-1.lock → gemfiles/mysql_ar_3.1.12.gemfile.lock
@@ -12,32 +12,35 @@ GEM
tzinfo (~> 0.3.29)
activesupport (3.1.12)
multi_json (~> 1.0)
+ appraisal (1.0.0.beta2)
+ bundler
+ rake
+ thor (>= 0.14.0)
arel (2.2.3)
builder (3.0.4)
columnize (0.3.6)
- debugger (1.5.0)
+ debugger (1.6.3)
columnize (>= 0.3.1)
debugger-linecache (~> 1.2.0)
- debugger-ruby_core_source (~> 1.2.0)
+ debugger-ruby_core_source (~> 1.2.4)
debugger-linecache (1.2.0)
- debugger-ruby_core_source (1.2.0)
- i18n (0.6.4)
- json (1.7.7)
- multi_json (1.7.2)
+ debugger-ruby_core_source (1.2.4)
+ i18n (0.6.9)
+ json (1.8.1)
+ multi_json (1.8.2)
mysql (2.9.1)
- pg (0.15.0)
+ rake (10.1.0)
rdoc (4.0.1)
json (~> 1.4)
- sqlite3 (1.3.7)
- tzinfo (0.3.37)
+ thor (0.18.1)
+ tzinfo (0.3.38)
PLATFORMS
ruby
DEPENDENCIES
- activerecord (~> 3.1.12)
+ activerecord (= 3.1.12)
+ appraisal (= 1.0.0.beta2)
debugger
mysql
- pg
rdoc
- sqlite3
View
9 gemfiles/mysql_ar_3.2.14.gemfile
@@ -0,0 +1,9 @@
+# This file was generated by Appraisal
+
+source "https://rubygems.org"
+
+gem "appraisal", "1.0.0.beta2"
+gem "debugger"
+gem "rdoc"
+gem "activerecord", "3.2.14"
+gem "mysql"
View
46 gemfiles/mysql_ar_3.2.14.gemfile.lock
@@ -0,0 +1,46 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ activemodel (3.2.14)
+ activesupport (= 3.2.14)
+ builder (~> 3.0.0)
+ activerecord (3.2.14)
+ activemodel (= 3.2.14)
+ activesupport (= 3.2.14)
+ arel (~> 3.0.2)
+ tzinfo (~> 0.3.29)
+ activesupport (3.2.14)
+ i18n (~> 0.6, >= 0.6.4)
+ multi_json (~> 1.0)
+ appraisal (1.0.0.beta2)
+ bundler
+ rake
+ thor (>= 0.14.0)
+ arel (3.0.3)
+ builder (3.0.4)
+ columnize (0.3.6)
+ debugger (1.6.3)
+ columnize (>= 0.3.1)
+ debugger-linecache (~> 1.2.0)
+ debugger-ruby_core_source (~> 1.2.4)
+ debugger-linecache (1.2.0)
+ debugger-ruby_core_source (1.2.4)
+ i18n (0.6.9)
+ json (1.8.1)
+ multi_json (1.8.2)
+ mysql (2.9.1)
+ rake (10.1.0)
+ rdoc (4.0.1)
+ json (~> 1.4)
+ thor (0.18.1)
+ tzinfo (0.3.38)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ activerecord (= 3.2.14)
+ appraisal (= 1.0.0.beta2)
+ debugger
+ mysql
+ rdoc
View
9 gemfiles/mysql_ar_4.0.1.gemfile
@@ -0,0 +1,9 @@
+# This file was generated by Appraisal
+
+source "https://rubygems.org"
+
+gem "appraisal", "1.0.0.beta2"
+gem "debugger"
+gem "rdoc"
+gem "activerecord", "4.0.1"
+gem "mysql"
View
54 gemfiles/mysql_ar_4.0.1.gemfile.lock
@@ -0,0 +1,54 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ activemodel (4.0.1)
+ activesupport (= 4.0.1)
+ builder (~> 3.1.0)
+ activerecord (4.0.1)
+ activemodel (= 4.0.1)
+ activerecord-deprecated_finders (~> 1.0.2)
+ activesupport (= 4.0.1)
+ arel (~> 4.0.0)
+ activerecord-deprecated_finders (1.0.3)
+ activesupport (4.0.1)
+ i18n (~> 0.6, >= 0.6.4)
+ minitest (~> 4.2)
+ multi_json (~> 1.3)
+ thread_safe (~> 0.1)
+ tzinfo (~> 0.3.37)
+ appraisal (1.0.0.beta2)
+ bundler
+ rake
+ thor (>= 0.14.0)
+ arel (4.0.1)
+ atomic (1.1.14)
+ builder (3.1.4)
+ columnize (0.3.6)
+ debugger (1.6.3)
+ columnize (>= 0.3.1)
+ debugger-linecache (~> 1.2.0)
+ debugger-ruby_core_source (~> 1.2.4)
+ debugger-linecache (1.2.0)
+ debugger-ruby_core_source (1.2.4)
+ i18n (0.6.9)
+ json (1.8.1)
+ minitest (4.7.5)
+ multi_json (1.8.2)
+ mysql (2.9.1)
+ rake (10.1.0)
+ rdoc (4.0.1)
+ json (~> 1.4)
+ thor (0.18.1)
+ thread_safe (0.1.3)
+ atomic
+ tzinfo (0.3.38)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ activerecord (= 4.0.1)
+ appraisal (= 1.0.0.beta2)
+ debugger
+ mysql
+ rdoc
View
9 gemfiles/pg_ar_3.0.20.gemfile
@@ -0,0 +1,9 @@
+# This file was generated by Appraisal
+
+source "https://rubygems.org"
+
+gem "appraisal", "1.0.0.beta2"
+gem "debugger"
+gem "rdoc"
+gem "activerecord", "3.0.20"
+gem "pg"
View
44 gemfiles/pg_ar_3.0.20.gemfile.lock
@@ -0,0 +1,44 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ activemodel (3.0.20)
+ activesupport (= 3.0.20)
+ builder (~> 2.1.2)
+ i18n (~> 0.5.0)
+ activerecord (3.0.20)
+ activemodel (= 3.0.20)
+ activesupport (= 3.0.20)
+ arel (~> 2.0.10)
+ tzinfo (~> 0.3.23)
+ activesupport (3.0.20)
+ appraisal (1.0.0.beta2)
+ bundler
+ rake
+ thor (>= 0.14.0)
+ arel (2.0.10)
+ builder (2.1.2)
+ columnize (0.3.6)
+ debugger (1.6.2)
+ columnize (>= 0.3.1)
+ debugger-linecache (~> 1.2.0)
+ debugger-ruby_core_source (~> 1.2.3)
+ debugger-linecache (1.2.0)
+ debugger-ruby_core_source (1.2.3)
+ i18n (0.5.0)
+ json (1.8.1)
+ pg (0.16.0)
+ rake (10.1.0)
+ rdoc (4.0.1)
+ json (~> 1.4)
+ thor (0.18.1)
+ tzinfo (0.3.38)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ activerecord (= 3.0.20)
+ appraisal (= 1.0.0.beta2)
+ debugger
+ pg
+ rdoc
View
9 gemfiles/pg_ar_3.1.12.gemfile
@@ -0,0 +1,9 @@
+# This file was generated by Appraisal
+
+source "https://rubygems.org"
+
+gem "appraisal", "1.0.0.beta2"
+gem "debugger"
+gem "rdoc"
+gem "activerecord", "3.1.12"
+gem "pg"
View
46 gemfiles/pg_ar_3.1.12.gemfile.lock
@@ -0,0 +1,46 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ activemodel (3.1.12)
+ activesupport (= 3.1.12)
+ builder (~> 3.0.0)
+ i18n (~> 0.6)
+ activerecord (3.1.12)
+ activemodel (= 3.1.12)
+ activesupport (= 3.1.12)
+ arel (~> 2.2.3)
+ tzinfo (~> 0.3.29)
+ activesupport (3.1.12)
+ multi_json (~> 1.0)
+ appraisal (1.0.0.beta2)
+ bundler
+ rake
+ thor (>= 0.14.0)
+ arel (2.2.3)
+ builder (3.0.4)
+ columnize (0.3.6)
+ debugger (1.6.3)
+ columnize (>= 0.3.1)
+ debugger-linecache (~> 1.2.0)
+ debugger-ruby_core_source (~> 1.2.4)
+ debugger-linecache (1.2.0)
+ debugger-ruby_core_source (1.2.4)
+ i18n (0.6.9)
+ json (1.8.1)
+ multi_json (1.8.2)
+ pg (0.16.0)
+ rake (10.1.0)
+ rdoc (4.0.1)
+ json (~> 1.4)
+ thor (0.18.1)
+ tzinfo (0.3.38)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ activerecord (= 3.1.12)
+ appraisal (= 1.0.0.beta2)
+ debugger
+ pg
+ rdoc
View
9 gemfiles/pg_ar_3.2.14.gemfile
@@ -0,0 +1,9 @@
+# This file was generated by Appraisal
+
+source "https://rubygems.org"
+
+gem "appraisal", "1.0.0.beta2"
+gem "debugger"
+gem "rdoc"
+gem "activerecord", "3.2.14"
+gem "pg"
View
46 gemfiles/pg_ar_3.2.14.gemfile.lock
@@ -0,0 +1,46 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ activemodel (3.2.14)
+ activesupport (= 3.2.14)
+ builder (~> 3.0.0)
+ activerecord (3.2.14)
+ activemodel (= 3.2.14)
+ activesupport (= 3.2.14)
+ arel (~> 3.0.2)
+ tzinfo (~> 0.3.29)
+ activesupport (3.2.14)
+ i18n (~> 0.6, >= 0.6.4)
+ multi_json (~> 1.0)
+ appraisal (1.0.0.beta2)
+ bundler
+ rake
+ thor (>= 0.14.0)
+ arel (3.0.3)
+ builder (3.0.4)
+ columnize (0.3.6)
+ debugger (1.6.3)
+ columnize (>= 0.3.1)
+ debugger-linecache (~> 1.2.0)
+ debugger-ruby_core_source (~> 1.2.4)
+ debugger-linecache (1.2.0)
+ debugger-ruby_core_source (1.2.4)
+ i18n (0.6.9)
+ json (1.8.1)
+ multi_json (1.8.2)
+ pg (0.16.0)
+ rake (10.1.0)
+ rdoc (4.0.1)
+ json (~> 1.4)
+ thor (0.18.1)
+ tzinfo (0.3.38)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ activerecord (= 3.2.14)
+ appraisal (= 1.0.0.beta2)
+ debugger
+ pg
+ rdoc
View
9 gemfiles/pg_ar_4.0.1.gemfile
@@ -0,0 +1,9 @@
+# This file was generated by Appraisal
+
+source "https://rubygems.org"
+
+gem "appraisal", "1.0.0.beta2"
+gem "debugger"
+gem "rdoc"
+gem "activerecord", "4.0.1"
+gem "pg"
View
54 gemfiles/pg_ar_4.0.1.gemfile.lock
@@ -0,0 +1,54 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ activemodel (4.0.1)
+ activesupport (= 4.0.1)
+ builder (~> 3.1.0)
+ activerecord (4.0.1)
+ activemodel (= 4.0.1)
+ activerecord-deprecated_finders (~> 1.0.2)
+ activesupport (= 4.0.1)
+ arel (~> 4.0.0)
+ activerecord-deprecated_finders (1.0.3)
+ activesupport (4.0.1)
+ i18n (~> 0.6, >= 0.6.4)
+ minitest (~> 4.2)
+ multi_json (~> 1.3)
+ thread_safe (~> 0.1)
+ tzinfo (~> 0.3.37)
+ appraisal (1.0.0.beta2)
+ bundler
+ rake
+ thor (>= 0.14.0)
+ arel (4.0.1)
+ atomic (1.1.14)
+ builder (3.1.4)
+ columnize (0.3.6)
+ debugger (1.6.3)
+ columnize (>= 0.3.1)
+ debugger-linecache (~> 1.2.0)
+ debugger-ruby_core_source (~> 1.2.4)
+ debugger-linecache (1.2.0)
+ debugger-ruby_core_source (1.2.4)
+ i18n (0.6.9)
+ json (1.8.1)
+ minitest (4.7.5)
+ multi_json (1.8.2)
+ pg (0.16.0)
+ rake (10.1.0)
+ rdoc (4.0.1)
+ json (~> 1.4)
+ thor (0.18.1)
+ thread_safe (0.1.3)
+ atomic
+ tzinfo (0.3.38)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ activerecord (= 4.0.1)
+ appraisal (= 1.0.0.beta2)
+ debugger
+ pg
+ rdoc
View
9 gemfiles/postgresql_ar_3.0.20.gemfile
@@ -0,0 +1,9 @@
+# This file was generated by Appraisal
+
+source "https://rubygems.org"
+
+gem "appraisal", "1.0.0.beta2"
+gem "debugger"
+gem "rdoc"
+gem "activerecord", "3.0.20"
+gem "postgresql"
View
9 gemfiles/postgresql_ar_3.1.12.gemfile
@@ -0,0 +1,9 @@
+# This file was generated by Appraisal
+
+source "https://rubygems.org"
+
+gem "appraisal", "1.0.0.beta2"
+gem "debugger"
+gem "rdoc"
+gem "activerecord", "3.1.12"
+gem "postgresql"
View
9 gemfiles/postgresql_ar_3.2.14.gemfile
@@ -0,0 +1,9 @@
+# This file was generated by Appraisal
+
+source "https://rubygems.org"
+
+gem "appraisal", "1.0.0.beta2"
+gem "debugger"
+gem "rdoc"
+gem "activerecord", "3.2.14"
+gem "postgresql"
View
9 gemfiles/postgresql_ar_4.0.1.gemfile
@@ -0,0 +1,9 @@
+# This file was generated by Appraisal
+
+source "https://rubygems.org"
+
+gem "appraisal", "1.0.0.beta2"
+gem "debugger"
+gem "rdoc"
+gem "activerecord", "4.0.1"
+gem "postgresql"
View
9 gemfiles/sqlite3_ar_3.0.20.gemfile
@@ -0,0 +1,9 @@
+# This file was generated by Appraisal
+
+source "https://rubygems.org"
+
+gem "appraisal", "1.0.0.beta2"
+gem "debugger"
+gem "rdoc"
+gem "activerecord", "3.0.20"
+gem "sqlite3"
View
44 gemfiles/sqlite3_ar_3.0.20.gemfile.lock
@@ -0,0 +1,44 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ activemodel (3.0.20)
+ activesupport (= 3.0.20)
+ builder (~> 2.1.2)
+ i18n (~> 0.5.0)
+ activerecord (3.0.20)
+ activemodel (= 3.0.20)
+ activesupport (= 3.0.20)
+ arel (~> 2.0.10)
+ tzinfo (~> 0.3.23)
+ activesupport (3.0.20)
+ appraisal (1.0.0.beta2)
+ bundler
+ rake
+ thor (>= 0.14.0)
+ arel (2.0.10)
+ builder (2.1.2)
+ columnize (0.3.6)
+ debugger (1.6.2)
+ columnize (>= 0.3.1)
+ debugger-linecache (~> 1.2.0)
+ debugger-ruby_core_source (~> 1.2.3)
+ debugger-linecache (1.2.0)
+ debugger-ruby_core_source (1.2.3)
+ i18n (0.5.0)
+ json (1.8.1)
+ rake (10.1.0)
+ rdoc (4.0.1)
+ json (~> 1.4)
+ sqlite3 (1.3.8)
+ thor (0.18.1)
+ tzinfo (0.3.38)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ activerecord (= 3.0.20)
+ appraisal (= 1.0.0.beta2)
+ debugger
+ rdoc
+ sqlite3
View
9 gemfiles/sqlite3_ar_3.1.12.gemfile
@@ -0,0 +1,9 @@
+# This file was generated by Appraisal
+
+source "https://rubygems.org"
+
+gem "appraisal", "1.0.0.beta2"
+gem "debugger"
+gem "rdoc"
+gem "activerecord", "3.1.12"
+gem "sqlite3"
View
46 gemfiles/sqlite3_ar_3.1.12.gemfile.lock
@@ -0,0 +1,46 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ activemodel (3.1.12)
+ activesupport (= 3.1.12)
+ builder (~> 3.0.0)
+ i18n (~> 0.6)
+ activerecord (3.1.12)
+ activemodel (= 3.1.12)
+ activesupport (= 3.1.12)
+ arel (~> 2.2.3)
+ tzinfo (~> 0.3.29)
+ activesupport (3.1.12)
+ multi_json (~> 1.0)
+ appraisal (1.0.0.beta2)
+ bundler
+ rake
+ thor (>= 0.14.0)
+ arel (2.2.3)
+ builder (3.0.4)
+ columnize (0.3.6)
+ debugger (1.6.3)
+ columnize (>= 0.3.1)
+ debugger-linecache (~> 1.2.0)
+ debugger-ruby_core_source (~> 1.2.4)
+ debugger-linecache (1.2.0)
+ debugger-ruby_core_source (1.2.4)
+ i18n (0.6.9)
+ json (1.8.1)
+ multi_json (1.8.2)
+ rake (10.1.0)
+ rdoc (4.0.1)
+ json (~> 1.4)
+ sqlite3 (1.3.8)
+ thor (0.18.1)
+ tzinfo (0.3.38)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ activerecord (= 3.1.12)
+ appraisal (= 1.0.0.beta2)
+ debugger
+ rdoc
+ sqlite3
View
9 gemfiles/sqlite3_ar_3.2.14.gemfile
@@ -0,0 +1,9 @@
+# This file was generated by Appraisal
+
+source "https://rubygems.org"
+
+gem "appraisal", "1.0.0.beta2"
+gem "debugger"
+gem "rdoc"
+gem "activerecord", "3.2.14"
+gem "sqlite3"
View
46 gemfiles/sqlite3_ar_3.2.14.gemfile.lock
@@ -0,0 +1,46 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ activemodel (3.2.14)
+ activesupport (= 3.2.14)
+ builder (~> 3.0.0)
+ activerecord (3.2.14)
+ activemodel (= 3.2.14)
+ activesupport (= 3.2.14)
+ arel (~> 3.0.2)
+ tzinfo (~> 0.3.29)
+ activesupport (3.2.14)
+ i18n (~> 0.6, >= 0.6.4)
+ multi_json (~> 1.0)
+ appraisal (1.0.0.beta2)
+ bundler
+ rake
+ thor (>= 0.14.0)
+ arel (3.0.3)
+ builder (3.0.4)
+ columnize (0.3.6)
+ debugger (1.6.3)
+ columnize (>= 0.3.1)
+ debugger-linecache (~> 1.2.0)
+ debugger-ruby_core_source (~> 1.2.4)
+ debugger-linecache (1.2.0)
+ debugger-ruby_core_source (1.2.4)
+ i18n (0.6.9)
+ json (1.8.1)
+ multi_json (1.8.2)
+ rake (10.1.0)
+ rdoc (4.0.1)
+ json (~> 1.4)
+ sqlite3 (1.3.8)
+ thor (0.18.1)
+ tzinfo (0.3.38)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ activerecord (= 3.2.14)
+ appraisal (= 1.0.0.beta2)
+ debugger
+ rdoc
+ sqlite3
View
9 gemfiles/sqlite3_ar_4.0.1.gemfile
@@ -0,0 +1,9 @@
+# This file was generated by Appraisal
+
+source "https://rubygems.org"
+
+gem "appraisal", "1.0.0.beta2"
+gem "debugger"
+gem "rdoc"
+gem "activerecord", "4.0.1"
+gem "sqlite3"
View
54 gemfiles/sqlite3_ar_4.0.1.gemfile.lock
@@ -0,0 +1,54 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ activemodel (4.0.1)
+ activesupport (= 4.0.1)
+ builder (~> 3.1.0)
+ activerecord (4.0.1)
+ activemodel (= 4.0.1)
+ activerecord-deprecated_finders (~> 1.0.2)
+ activesupport (= 4.0.1)
+ arel (~> 4.0.0)
+ activerecord-deprecated_finders (1.0.3)
+ activesupport (4.0.1)
+ i18n (~> 0.6, >= 0.6.4)
+ minitest (~> 4.2)
+ multi_json (~> 1.3)
+ thread_safe (~> 0.1)
+ tzinfo (~> 0.3.37)
+ appraisal (1.0.0.beta2)
+ bundler
+ rake
+ thor (>= 0.14.0)
+ arel (4.0.1)
+ atomic (1.1.14)
+ builder (3.1.4)
+ columnize (0.3.6)
+ debugger (1.6.3)
+ columnize (>= 0.3.1)
+ debugger-linecache (~> 1.2.0)
+ debugger-ruby_core_source (~> 1.2.4)
+ debugger-linecache (1.2.0)
+ debugger-ruby_core_source (1.2.4)
+ i18n (0.6.9)
+ json (1.8.1)
+ minitest (4.7.5)
+ multi_json (1.8.2)
+ rake (10.1.0)
+ rdoc (4.0.1)
+ json (~> 1.4)
+ sqlite3 (1.3.8)
+ thor (0.18.1)
+ thread_safe (0.1.3)
+ atomic
+ tzinfo (0.3.38)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ activerecord (= 4.0.1)
+ appraisal (= 1.0.0.beta2)
+ debugger
+ rdoc
+ sqlite3
View
8 lib/ancestry.rb
@@ -1,7 +1,7 @@
-require File.join(File.expand_path(File.dirname(__FILE__)), 'ancestry/class_methods')
-require File.join(File.expand_path(File.dirname(__FILE__)), 'ancestry/instance_methods')
-require File.join(File.expand_path(File.dirname(__FILE__)), 'ancestry/exceptions')
-require File.join(File.expand_path(File.dirname(__FILE__)), 'ancestry/has_ancestry')
+require_relative 'ancestry/class_methods'
+require_relative 'ancestry/instance_methods'
+require_relative 'ancestry/exceptions'
+require_relative 'ancestry/has_ancestry'
module Ancestry
ANCESTRY_PATTERN = /\A[0-9]+(\/[0-9]+)*\Z/
View
4 lib/ancestry/instance_methods.rb
@@ -273,14 +273,14 @@ def cast_primary_key(key)
def primary_key_type
@primary_key_type ||= column_for_attribute(self.class.primary_key).type
end
+
def unscoped_descendants
self.ancestry_base_class.unscoped do
self.ancestry_base_class.where descendant_conditions
end
end
- # basically validates the ancestry, but also applied if validation is
- # bypassed to determine if chidren should be affected
+ # Validates the ancestry, but can also be applied if validation is bypassed to determine if chidren should be affected
def sane_ancestry?
ancestry.nil? || (ancestry.to_s =~ Ancestry::ANCESTRY_PATTERN && !ancestor_ids.include?(self.id))
end
View
80 test/concerns/arrangement_test.rb
@@ -0,0 +1,80 @@
+require_relative '../environment'
+
+class ArrangementTest < ActiveSupport::TestCase
+ def test_arrangement
+ 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 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_arrange_serializable
+ AncestryTestDatabase.with_model :depth => 2, :width => 2 do |model, roots|
+ result = [{"ancestry"=>nil,
+ "id"=>4,
+ "children"=>
+ [{"ancestry"=>"4", "id"=>6, "children"=>[]},
+ {"ancestry"=>"4", "id"=>5, "children"=>[]}]},
+ {"ancestry"=>nil,
+ "id"=>1,
+ "children"=>
+ [{"ancestry"=>"1", "id"=>3, "children"=>[]},
+ {"ancestry"=>"1", "id"=>2, "children"=>[]}]}]
+
+ assert_equal model.arrange_serializable(order: "id desc"), result
+ end
+ end
+
+ def test_arrange_order_option
+ 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]
+ ascending_nodes_lvl1 = ascending_nodes_lvl0[ascending_node]
+ descending_nodes_lvl1.keys.zip(ascending_nodes_lvl1.keys.reverse).each do |descending_node, ascending_node|
+ assert_equal descending_node, ascending_node
+ descending_nodes_lvl2 = descending_nodes_lvl1[descending_node]
+ ascending_nodes_lvl2 = ascending_nodes_lvl1[ascending_node]
+ descending_nodes_lvl2.keys.zip(ascending_nodes_lvl2.keys.reverse).each do |descending_node, ascending_node|
+ assert_equal descending_node, ascending_node
+ descending_nodes_lvl3 = descending_nodes_lvl2[descending_node]
+ ascending_nodes_lvl3 = ascending_nodes_lvl2[ascending_node]
+ descending_nodes_lvl3.keys.zip(ascending_nodes_lvl3.keys.reverse).each do |descending_node, ascending_node|
+ assert_equal descending_node, ascending_node
+ end
+ end
+ end
+ end
+ end
+ end
+
+ def test_arrangement_nesting
+ AncestryTestDatabase.with_model :extra_columns => {:name => :string} do |model|
+
+ # Rails < 3.1 doesn't support lambda default_scopes (only hashes)
+ # But Rails >= 4 logs deprecation warnings for hash default_scopes
+ if ActiveRecord::VERSION::STRING < "3.1"
+ model.send :default_scope, model.order('name')
+ else
+ model.send :default_scope, lambda { model.order('name') }
+ end
+
+ model.create!(:name => 'Linux').children.create! :name => 'Debian'
+
+ assert_equal 1, model.arrange.count
+ end
+ end
+end
View
44 test/concerns/build_ancestry_test.rb
@@ -0,0 +1,44 @@
+require_relative '../environment'
+
+class BuildAncestryTest < ActiveSupport::TestCase
+ def test_build_ancestry_from_parent_ids
+ 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
+
+ # Assert all nodes where created
+ assert_equal (0..3).map { |n| 5 ** n }.sum, 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.to_a
+ # Assert single root node
+ assert_equal 1, roots.size
+
+ # Assert it has 5 children
+ roots.each do |parent|
+ assert_equal 5, parent.children.count
+ parent.children.each do |parent|
+ assert_equal 5, parent.children.count
+ parent.children.each do |parent|
+ assert_equal 5, parent.children.count
+ parent.children.each do |parent|
+ assert_equal 0, parent.children.count
+ end
+ end
+ end
+ end
+ end
+ end
+end
View
56 test/concerns/default_scopes_test.rb
@@ -0,0 +1,56 @@
+require_relative '../environment'
+
+class DefaultScopesTest < ActiveSupport::TestCase
+ def test_node_excluded_by_default_scope_should_still_move_with_parent
+ AncestryTestDatabase.with_model(
+ :width => 3, :depth => 3, :extra_columns => {:deleted_at => :datetime},
+ :default_scope_params => {:deleted_at => nil}
+ ) do |model, roots|
+ roots = model.roots.to_a
+ grandparent = roots[0]
+ new_grandparent = roots[1]
+ parent = grandparent.children.first
+ child = parent.children.first
+
+ child.update_attributes :deleted_at => Time.now
+ parent.update_attributes :parent => new_grandparent
+ child.update_attributes :deleted_at => nil
+
+ assert child.reload.ancestors.include? new_grandparent
+ end
+ end
+
+ def test_node_excluded_by_default_scope_should_be_destroyed_with_parent
+ AncestryTestDatabase.with_model(
+ :width => 1, :depth => 2, :extra_columns => {:deleted_at => :datetime},
+ :default_scope_params => {:deleted_at => nil},
+ :orphan_strategy => :destroy
+ ) do |model, roots|
+ parent = model.roots.first
+ child = parent.children.first
+
+ child.update_attributes :deleted_at => Time.now
+ parent.destroy
+ child.update_attributes :deleted_at => nil
+
+ assert model.count.zero?
+ end
+ end
+
+ def test_node_excluded_by_default_scope_should_be_rootified
+ AncestryTestDatabase.with_model(
+ :width => 1, :depth => 2, :extra_columns => {:deleted_at => :datetime},
+ :default_scope_params => {:deleted_at => nil},
+ :orphan_strategy => :rootify
+ ) do |model, roots|
+ parent = model.roots.first
+ child = parent.children.first
+
+ child.update_attributes :deleted_at => Time.now
+ parent.destroy
+ child.update_attributes :deleted_at => nil
+
+ assert child.reload.is_root?
+ end
+ end
+end
View
93 test/concerns/depth_caching_test.rb
@@ -0,0 +1,93 @@
+require_relative '../environment'
+
+class DepthCachingTest < ActiveSupport::TestCase
+ def test_depth_caching
+ 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_caching_after_subtree_movement
+ AncestryTestDatabase.with_model :depth => 6, :width => 1, :cache_depth => true, :depth_cache_column => :depth_cache do |model, roots|
+ node = model.at_depth(3).first
+ node.update_attributes(:parent => model.roots.first)
+ assert_equal(1, node.depth_cache)
+ node.descendants.each do |descendant|
+ assert_equal(descendant.depth, descendant.depth_cache)
+ end
+ end
+ end
+
+ def test_depth_scopes
+ 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
+ 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
+
+ def test_rebuild_depth_cache
+ 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
+ model.all.each do |test_node|
+ assert_equal nil, test_node.depth_cache
+ end
+
+ # Rebuild cache
+ model.rebuild_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
+ AncestryTestDatabase.with_model do |model|
+ assert_raise Ancestry::AncestryException do
+ model.rebuild_depth_cache!
+ end
+ end
+ end
+
+ def test_exception_on_unknown_depth_column
+ 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
+end
View
58 test/concerns/depth_constraints_test.rb
@@ -0,0 +1,58 @@
+require_relative '../environment'
+
+class DepthConstraintsTest < ActiveSupport::TestCase
+ def test_descendants_with_depth_constraints
+ 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
+ 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
+ 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
+ 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
+end
View
81 test/concerns/has_ancestry_test.rb
@@ -0,0 +1,81 @@
+require_relative '../environment'
+
+class HasAncestryTreeTest < ActiveSupport::TestCase
+ def test_default_ancestry_column
+ AncestryTestDatabase.with_model do |model|
+ assert_equal :ancestry, model.ancestry_column
+ end
+ end
+
+ def test_non_default_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
+ 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_invalid_has_ancestry_options
+ assert_raise Ancestry::AncestryException do
+ Class.new(ActiveRecord::Base).has_ancestry :this_option_doesnt_exist => 42
+ end
+ assert_raise Ancestry::AncestryException do
+ Class.new(ActiveRecord::Base).has_ancestry :not_a_hash
+ end
+ end
+
+ def test_descendants_move_with_node
+ 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
+ assert_no_difference 'root2.descendants.size' do
+ assert_difference 'root3.descendants.size', root2.subtree.size do
+ root2.parent = root3
+ root2.save!
+ 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!
+ end
+ end
+ end
+ end
+ end
+
+ def test_setup_test_nodes
+ 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|
+ assert_equal model, node.class
+ assert_equal Array, children.class
+ assert_equal 3, children.length
+ children.each do |node, children|
+ assert_equal model, node.class
+ assert_equal Array, children.class
+ assert_equal 3, children.length
+ children.each do |node, children|
+ assert_equal model, node.class
+ assert_equal Array, children.class
+ assert_equal 0, children.length
+ end
+ end
+ end
+ end
+ end
+end
View
92 test/concerns/integrity_checking_and_restoration_test.rb
@@ -0,0 +1,92 @@
+require_relative '../environment'
+
+class IntegrityCheckingAndRestaurationTest < ActiveSupport::TestCase
+ def test_integrity_checking
+ 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
+ assert_equal 0, model.check_ancestry_integrity!(:report => :list).size
+ end
+
+ 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
+ assert_equal 1, model.check_ancestry_integrity!(:report => :list).size
+ end
+
+ 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
+ assert_equal 1, model.check_ancestry_integrity!(:report => :list).size
+ end
+
+ 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
+ assert_equal 1, model.check_ancestry_integrity!(:report => :list).size
+ end
+
+ 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
+ assert_equal 1, model.check_ancestry_integrity!(:report => :list).size
+ end
+ end
+
+ def assert_integrity_restoration model
+ assert_raise Ancestry::AncestryIntegrityException do
+ model.check_ancestry_integrity!
+ end
+ model.restore_ancestry_integrity!
+ assert_nothing_raised do
+ model.check_ancestry_integrity!
+ end
+ assert model.all.any? {|node| node.ancestry.present? }, "Expected some nodes not to be roots"
+ assert_equal model.count, model.roots.collect {|node| node.descendants.count + 1 }.sum
+ end
+
+ def test_integrity_restoration
+ width, depth = 3, 3
+ # Check that integrity is restored for invalid format for ancestry column
+ AncestryTestDatabase.with_model :width => width, :depth => depth 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
+ AncestryTestDatabase.with_model :width => width, :depth => depth 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
+ AncestryTestDatabase.with_model :width => width, :depth => depth 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
+ 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
+end
View
90 test/concerns/orphan_strategies_test.rb
@@ -0,0 +1,90 @@
+require_relative '../environment'
+
+class OphanStrategiesTest < ActiveSupport::TestCase
+ def test_default_orphan_strategy
+ AncestryTestDatabase.with_model do |model|
+ assert_equal :destroy, model.orphan_strategy
+ end
+ end
+
+ def test_non_default_orphan_strategy
+ AncestryTestDatabase.with_model :orphan_strategy => :rootify do |model|
+ assert_equal :rootify, model.orphan_strategy
+ end
+ end
+
+ def test_setting_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
+ AncestryTestDatabase.with_model do |model|
+ assert_raise Ancestry::AncestryException do
+ model.orphan_strategy = :non_existent_orphan_strategy
+ end
+ end
+ end
+
+ def test_orphan_rootify_strategy
+ AncestryTestDatabase.with_model :depth => 3, :width => 3 do |model, roots|
+ model.orphan_strategy = :rootify
+ root = roots.first.first
+ children = root.children.to_a
+ 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
+ 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
+ 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_orphan_adopt_strategy
+ AncestryTestDatabase.with_model do |model|
+ model.orphan_strategy = :adopt # set the orphan strategy as paerntify
+ n1 = model.create! #create a root node
+ n2 = model.create!(:parent => n1) #create child with parent=root
+ n3 = model.create!(:parent => n2) #create child with parent=n2, depth = 2
+ n4 = model.create!(:parent => n2) #create child with parent=n2, depth = 2
+ n5 = model.create!(:parent => n4) #create child with parent=n4, depth = 3
+ n2.destroy # delete a node with desecendants
+ assert_equal(model.find(n3.id).parent,n1, "orphan's not parentified" )
+ assert_equal(model.find(n5.id).ancestor_ids,[n1.id,n4.id], "ancestry integrity not maintained")
+ n1.destroy # delete a root node with desecendants
+ assert_equal(model.find(n3.id).parent_id,nil," Children of the deleted root not rootfied")
+ assert_equal(model.find(n5.id).ancestor_ids,[n4.id],"ancestry integrity not maintained")
+ end
+ end
+end
View
69 test/concerns/scopes_test.rb
@@ -0,0 +1,69 @@
+require_relative '../environment'
+
+class ScopesTest < ActiveSupport::TestCase
+ def test_scopes
+ AncestryTestDatabase.with_model :depth => 3, :width => 3 do |model, roots|
+ # Roots assertion
+ assert_equal roots.map(&:first), model.roots.to_a
+
+ model.all.each do |test_node|
+ # Assertions for ancestors_of named scope
+ assert_equal test_node.ancestors.to_a, model.ancestors_of(test_node).to_a
+ assert_equal test_node.ancestors.to_a, model.ancestors_of(test_node.id).to_a
+ # Assertions for children_of named scope
+ assert_equal test_node.children.to_a, model.children_of(test_node).to_a
+ assert_equal test_node.children.to_a, model.children_of(test_node.id).to_a
+ # Assertions for descendants_of named scope
+ assert_equal test_node.descendants.to_a, model.descendants_of(test_node).to_a
+ assert_equal test_node.descendants.to_a, model.descendants_of(test_node.id).to_a
+ # Assertions for subtree_of named scope
+ assert_equal test_node.subtree.to_a, model.subtree_of(test_node).to_a
+ assert_equal test_node.subtree.to_a, model.subtree_of(test_node.id).to_a
+ # Assertions for siblings_of named scope
+ assert_equal test_node.siblings.to_a, model.siblings_of(test_node).to_a
+ assert_equal test_node.siblings.to_a, model.siblings_of(test_node.id).to_a
+ end
+ end
+ end
+
+ def test_node_creation_through_scope
+ 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_scoping_in_callbacks
+ AncestryTestDatabase.with_model do |model|
+ record = model.create
+
+ model.instance_eval do
+ after_create :after_create_callback
+ end
+
+ model.class_eval do
+ define_method :after_create_callback do
+ # We don't want to be in the #children scope here when creating the child
+ self.parent
+ self.parent_id = record.id if record
+ self.root
+ end
+ end
+
+ parent = model.create
+ assert child = parent.children.create
+ end
+ end
+end
View
30 test/concerns/sort_by_ancestry_test.rb
@@ -0,0 +1,30 @@
+require_relative '../environment'
+
+class SortByAncestryTest < ActiveSupport::TestCase
+ def test_sort_by_ancestry
+ AncestryTestDatabase.with_model do |model|
+ n1 = model.create!
+ n2 = model.create!(:parent => n1)
+ n3 = model.create!(:parent => n2)
+ n4 = model.create!(:parent => n2)
+ n5 = model.create!(:parent => n1)
+
+ records = model.sort_by_ancestry(model.all.sort_by(&:id).reverse)
+ assert_equal [n1, n2, n4, n3, n5].map(&:id), records.map(&:id)
+ end
+ end
+
+ def test_sort_by_ancestry_with_block
+ AncestryTestDatabase.with_model :extra_columns => {:rank => :integer} do |model|
+ n1 = model.create!(:rank => 0)
+ n2 = model.create!(:rank => 1)
+ n3 = model.create!(:rank => 0, :parent => n1)
+ n4 = model.create!(:rank => 0, :parent => n2)
+ n5 = model.create!(:rank => 1, :parent => n1)
+ n6 = model.create!(:rank => 1, :parent => n2)
+
+ records = model.sort_by_ancestry(model.all.sort_by(&:rank).reverse) {|a, b| a.rank <=> b.rank}
+ assert_equal [n1, n3, n5, n2, n4, n6].map(&:id), records.map(&:id)
+ end
+ end
+end
View
37 test/concerns/sti_support_test.rb
@@ -0,0 +1,37 @@
+require_relative '../environment'
+
+class StiSupportTest < ActiveSupport::TestCase
+ def test_sti_support
+ 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_sti_support_with_from_subclass
+ AncestryTestDatabase.with_model :extra_columns => {:type => :string} do |model|
+ subclass1 = Object.const_set 'SubclassWithAncestry', Class.new(model)
+
+ subclass1.has_ancestry
+
+ subclass1.create!
+ end
+ end
+end
View
47 test/concerns/touching_test.rb
@@ -0,0 +1,47 @@
+require_relative '../environment'
+
+class TouchingTest < ActiveSupport::TestCase
+ def test_touch_option_disabled
+ AncestryTestDatabase.with_model(
+ :extra_columns => {:name => :string, :updated_at => :datetime},
+ :touch => false
+ ) do |model|
+
+ yesterday = Time.now - 1.day
+ parent = model.create!(:updated_at => yesterday)
+ child = model.create!(:updated_at => yesterday, :parent => parent)
+
+ child.update_attributes(:name => "Changed")
+ assert_equal yesterday, parent.updated_at
+ end
+ end
+
+ def test_touch_option_enabled
+ AncestryTestDatabase.with_model(
+ :extra_columns => {:updated_at => :datetime},
+ :touch => true
+ ) do |model|
+
+ way_back = Time.new(1984)
+ recently = Time.now - 1.minute
+
+ parent_1 = model.create!(:updated_at => way_back)
+ parent_2 = model.create!(:updated_at => way_back)
+ child_1_1 = model.create!(:updated_at => way_back, :parent => parent_1)
+ child_1_2 = model.create!(:updated_at => way_back, :parent => parent_1)
+ grandchild_1_1_1 = model.create!(:updated_at => way_back, :parent => child_1_1)
+ grandchild_1_1_2 = model.create!(:updated_at => way_back, :parent => child_1_1)
+
+ grandchild_1_1_1.parent = parent_2
+ grandchild_1_1_1.save!
+
+ assert grandchild_1_1_1.reload.updated_at > recently, "record was not touched"
+ assert child_1_1.reload.updated_at > recently, "old parent was not touched"
+ assert parent_1.reload.updated_at > recently, "old grandparent was not touched"
+ assert parent_2.reload.updated_at > recently, "new parent was not touched"
+
+ assert_equal way_back, grandchild_1_1_2.reload.updated_at, "old sibling was touched"
+ assert_equal way_back, child_1_2.reload.updated_at, "unrelated record was touched"
+ end
+ end
+end
View
109 test/concerns/tree_navigration_test.rb
@@ -0,0 +1,109 @@
+require_relative '../environment'
+
+class TreeNavigationTest < ActiveSupport::TestCase
+ def test_tree_navigation
+ AncestryTestDatabase.with_model :depth => 3, :width => 3 do |model, roots|
+ 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
+ refute lvl0_node.parent_id?
+ # 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 = model.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|
+ # 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
+ # Parent assertions
+ assert_equal lvl0_node.id, lvl1_node.parent_id
+ assert_equal lvl0_node, lvl1_node.parent
+ assert lvl1_node.parent_id?
+ # Root assertions
+ 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 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 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 = 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
+ assert lvl2_node.parent_id?
+ # 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
+ end
+ end
+ end
+ end
+end
View
27 test/concerns/validations_test.rb
@@ -0,0 +1,27 @@
+require_relative '../environment'
+
+class ValidationsTest < ActiveSupport::TestCase
+ 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_validate_ancestry_exclude_self
+ 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
+end
View
25 test/environment.rb
@@ -1,22 +1,33 @@
require 'rubygems'
require 'bundler/setup'
-
require 'active_record'
require 'active_support/test_case'
require 'active_support/buffered_logger'
require 'test/unit'
+require 'debugger'
-# this is to make absolutely sure we test this one, not the one
-# installed on the system.
+# Make absolutely sure we are testing local ancestry
require File.expand_path('../../lib/ancestry', __FILE__)
-require 'debugger' if RUBY_VERSION =~ /\A1.9/
-
class AncestryTestDatabase
def self.setup
+ # Silence I18n
+ I18n.enforce_available_locales = false if I18n.respond_to? :enforce_available_locales=
+
+ # Setup logger
logger = ActiveSupport.const_defined?(:Logger) ? :Logger : :BufferedLogger
ActiveRecord::Base.logger = ActiveSupport.const_get(logger).new('log/test.log')
- ActiveRecord::Base.establish_connection YAML.load(File.open(File.expand_path('../database.yml', __FILE__)).read)[ENV['db'] || 'sqlite3']
+
+ # Setup database connection
+ YAML.load(File.open(File.expand_path('../database.yml', __FILE__)).read).values.each do |config|
+ begin
+ ActiveRecord::Base.establish_connection config
+ break if ActiveRecord::Base.connection
+ rescue LoadError, RuntimeError
+ # Try if adapter can be loaded for next config
+ end
+ end
+ raise 'Could not load any database adapter!' unless ActiveRecord::Base.connected?
end
def self.with_model options = {}
@@ -79,7 +90,7 @@ def self.create_test_nodes model, depth, width, parent = nil
AncestryTestDatabase.setup
-puts "\nRunning Ancestry test suite:"
+puts "\nLoaded Ancestry test suite environment:"
puts " Ruby: #{RUBY_VERSION}"
puts " ActiveRecord: #{ActiveRecord::VERSION::STRING}"
puts " Database: #{ActiveRecord::Base.connection.adapter_name}\n\n"
View
873 test/has_ancestry_test.rb
@@ -1,873 +0,0 @@
-require "environment"
-
-class HasAncestryTreeTest < ActiveSupport::TestCase
- def test_default_ancestry_column
- AncestryTestDatabase.with_model do |model|
- assert_equal :ancestry, model.ancestry_column
- end
- end
-
- def test_non_default_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
- 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
- AncestryTestDatabase.with_model do |model|
- assert_equal :destroy, model.orphan_strategy
- end
- end
-
- def test_non_default_orphan_strategy
- AncestryTestDatabase.with_model :orphan_strategy => :rootify do |model|
- assert_equal :rootify, model.orphan_strategy
- end
- end
-
- def test_setting_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
- AncestryTestDatabase.with_model do |model|
- assert_raise Ancestry::AncestryException do
- model.orphan_strategy = :non_existent_orphan_strategy
- end
- end
- end
-
- def test_scoping_in_callbacks
- AncestryTestDatabase.with_model do |model|
- $random_object = model.create
-
- model.instance_eval do
- after_create :after_create_callback
- end
- model.class_eval do
- def after_create_callback
- # We don't want to be in the #children scope here when creating the child
- self.parent
- self.parent_id = $random_object.id if $random_object
- self.root
- end
- end
-
- parent = model.create
- assert child = parent.children.create
- end
- end
-
- def test_setup_test_nodes
- 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|
- assert_equal model, node.class
- assert_equal Array, children.class
- assert_equal 3, children.length
- children.each do |node, children|
- assert_equal model, node.class
- assert_equal Array, children.class
- assert_equal 3, children.length
- children.each do |node, children|
- assert_equal model, node.class
- assert_equal Array, children.class
- assert_equal 0, children.length
- end
- end
- end
- end
- end
-
- def test_tree_navigation
- AncestryTestDatabase.with_model :depth => 3, :width => 3 do |model, roots|
- 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
- refute lvl0_node.parent_id?
- # 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 = model.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|
- # 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
- # Parent assertions
- assert_equal lvl0_node.id, lvl1_node.parent_id
- assert_equal lvl0_node, lvl1_node.parent
- assert lvl1_node.parent_id?
- # Root assertions
- 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 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 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 = 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
- assert lvl2_node.parent_id?
- # 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