dagnabit 2.2.6 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. data/History.md +105 -0
  2. data/LICENSE +1 -1
  3. data/MIGRATION.md +56 -0
  4. data/README.md +222 -0
  5. data/bin/dagnabit-test +11 -31
  6. data/db/connection.rb +3 -0
  7. data/{test/connections/native_postgresql → db/connections/postgresql}/connection.rb +6 -5
  8. data/db/models/edge.rb +6 -0
  9. data/db/models/other_edge.rb +6 -0
  10. data/db/models/other_vertex.rb +6 -0
  11. data/db/models/vertex.rb +6 -0
  12. data/db/schema.rb +32 -0
  13. data/lib/dagnabit.rb +6 -19
  14. data/lib/dagnabit/edge.rb +7 -0
  15. data/lib/dagnabit/edge/activation.rb +14 -0
  16. data/lib/dagnabit/edge/associations.rb +10 -0
  17. data/lib/dagnabit/edge/connectivity.rb +38 -0
  18. data/lib/dagnabit/graph.rb +143 -0
  19. data/lib/dagnabit/migration.rb +98 -0
  20. data/lib/dagnabit/version.rb +3 -0
  21. data/lib/dagnabit/vertex.rb +10 -0
  22. data/lib/dagnabit/vertex/activation.rb +19 -0
  23. data/lib/dagnabit/vertex/associations.rb +24 -0
  24. data/lib/dagnabit/vertex/bonding.rb +43 -0
  25. data/lib/dagnabit/vertex/connectivity.rb +130 -0
  26. data/lib/dagnabit/vertex/neighbors.rb +50 -0
  27. data/lib/dagnabit/vertex/settings.rb +56 -0
  28. metadata +94 -143
  29. data/.autotest +0 -5
  30. data/.document +0 -5
  31. data/.gitignore +0 -7
  32. data/Gemfile +0 -15
  33. data/Gemfile.lock +0 -38
  34. data/History.txt +0 -81
  35. data/README.rdoc +0 -202
  36. data/Rakefile +0 -52
  37. data/VERSION.yml +0 -5
  38. data/dagnabit.gemspec +0 -142
  39. data/init.rb +0 -1
  40. data/lib/dagnabit/activation.rb +0 -60
  41. data/lib/dagnabit/link/associations.rb +0 -18
  42. data/lib/dagnabit/link/class_methods.rb +0 -43
  43. data/lib/dagnabit/link/configuration.rb +0 -40
  44. data/lib/dagnabit/link/cycle_prevention.rb +0 -31
  45. data/lib/dagnabit/link/named_scopes.rb +0 -65
  46. data/lib/dagnabit/link/transitive_closure_link_model.rb +0 -86
  47. data/lib/dagnabit/link/transitive_closure_recalculation.rb +0 -17
  48. data/lib/dagnabit/link/transitive_closure_recalculation/on_create.rb +0 -104
  49. data/lib/dagnabit/link/transitive_closure_recalculation/on_destroy.rb +0 -125
  50. data/lib/dagnabit/link/transitive_closure_recalculation/on_update.rb +0 -17
  51. data/lib/dagnabit/link/transitive_closure_recalculation/utilities.rb +0 -56
  52. data/lib/dagnabit/link/validations.rb +0 -26
  53. data/lib/dagnabit/node/associations.rb +0 -84
  54. data/lib/dagnabit/node/class_methods.rb +0 -74
  55. data/lib/dagnabit/node/configuration.rb +0 -26
  56. data/lib/dagnabit/node/neighbors.rb +0 -73
  57. data/test/connections/native_sqlite3/connection.rb +0 -24
  58. data/test/dagnabit/link/test_associations.rb +0 -61
  59. data/test/dagnabit/link/test_class_methods.rb +0 -102
  60. data/test/dagnabit/link/test_configuration.rb +0 -38
  61. data/test/dagnabit/link/test_cycle_prevention.rb +0 -64
  62. data/test/dagnabit/link/test_named_scopes.rb +0 -32
  63. data/test/dagnabit/link/test_transitive_closure_link_model.rb +0 -69
  64. data/test/dagnabit/link/test_transitive_closure_recalculation.rb +0 -178
  65. data/test/dagnabit/link/test_validations.rb +0 -39
  66. data/test/dagnabit/node/test_associations.rb +0 -147
  67. data/test/dagnabit/node/test_class_methods.rb +0 -49
  68. data/test/dagnabit/node/test_configuration.rb +0 -29
  69. data/test/dagnabit/node/test_neighbors.rb +0 -91
  70. data/test/helper.rb +0 -26
  71. data/test/models/beta_node.rb +0 -3
  72. data/test/models/custom_data_link.rb +0 -4
  73. data/test/models/customized_link.rb +0 -7
  74. data/test/models/customized_link_node.rb +0 -4
  75. data/test/models/link.rb +0 -4
  76. data/test/models/node.rb +0 -3
  77. data/test/schema/schema.rb +0 -51
@@ -1,24 +0,0 @@
1
- print "Using native SQLite3\n"
2
-
3
- require 'logger'
4
-
5
- # The SQLite3 Ruby driver can be present as either a gem or directly present in
6
- # the Ruby library load path. This load method addresses these two situations.
7
- begin
8
- require 'sqlite3'
9
- rescue LoadError
10
- require 'rubygems'
11
- gem 'sqlite3-ruby'
12
- require 'sqlite3'
13
- end
14
-
15
- ActiveRecord::Base.logger = Logger.new("debug.log")
16
-
17
- class SqliteError < StandardError
18
- end
19
-
20
- ActiveRecord::Base.configurations = {
21
- 'ActiveRecord::Base' => { :adapter => 'sqlite3', :database => ':memory:' }
22
- };
23
-
24
- ActiveRecord::Base.establish_connection('ActiveRecord::Base')
@@ -1,61 +0,0 @@
1
- require 'helper'
2
-
3
- module Dagnabit
4
- module Link
5
- class TestAssociations < ActiveRecord::TestCase
6
- class Node < ActiveRecord::Base
7
- set_table_name 'nodes'
8
- end
9
-
10
- class Link < ActiveRecord::Base
11
- set_table_name 'edges'
12
- extend Dagnabit::Link::Configuration
13
- configure_acts_as_dag_link({})
14
- extend Dagnabit::Link::Associations
15
- end
16
-
17
- class CustomLink < ActiveRecord::Base
18
- set_table_name 'other_name_edges'
19
-
20
- extend Dagnabit::Link::Configuration
21
- configure_acts_as_dag_link(:ancestor_id_column => 'the_ancestor_id',
22
- :descendant_id_column => 'the_descendant_id',
23
- :transitive_closure_table_name => 'my_transitive_closure')
24
-
25
- extend Dagnabit::Link::Associations
26
- end
27
-
28
- def setup
29
- @node = Node.new
30
- @link = Link.new
31
- @custom_link = CustomLink.new
32
- end
33
-
34
- should 'add an ancestor association proxy' do
35
- @link.ancestor = @node
36
- @link.save
37
- assert_equal @node, @link.reload.ancestor
38
- end
39
-
40
- should 'add a descendant association proxy' do
41
- @link.descendant = @node
42
- @link.save
43
- assert_equal @node, @link.reload.descendant
44
- end
45
-
46
- should 'permit customization of the ancestor association foreign key' do
47
- @custom_link.ancestor = @node
48
- @custom_link.save
49
- @custom_link = CustomLink.find(@custom_link.id)
50
- assert_equal @node, @custom_link.ancestor
51
- end
52
-
53
- should 'permit customization of the descendant association foreign key' do
54
- @custom_link.descendant = @node
55
- @custom_link.save
56
- @custom_link = CustomLink.find(@custom_link.id)
57
- assert_equal @node, @custom_link.descendant
58
- end
59
- end
60
- end
61
- end
@@ -1,102 +0,0 @@
1
- require 'helper'
2
-
3
- module Dagnabit
4
- module Link
5
- class TestClassMethods < ActiveRecord::TestCase
6
- should 'include a method to build edges' do
7
- n1 = ::Node.new
8
- n2 = ::Node.new
9
-
10
- link = ::Link.build_edge(n1, n2)
11
- assert_equal n1, link.ancestor
12
- assert_equal n2, link.descendant
13
- end
14
-
15
- should 'permit custom data to be included on edges' do
16
- n1 = ::Node.new
17
- n2 = ::Node.new
18
-
19
- link = CustomDataLink.build_edge(n1, n2, :data => 'foobar')
20
- assert_equal 'foobar', link.data
21
- end
22
-
23
- context 'connect' do
24
- should 'connect two nodes' do
25
- n1 = ::Node.new
26
- n2 = ::Node.new
27
-
28
- ::Link.connect(n1, n2)
29
- link = ::Link.find(:first, :conditions => { :ancestor_id => n1.id, :descendant_id => n2.id })
30
-
31
- assert_not_nil link
32
- assert_equal n1, link.ancestor
33
- assert_equal n2, link.descendant
34
- end
35
-
36
- should 'permit custom data to be included on edges' do
37
- n1 = ::Node.new
38
- n2 = ::Node.new
39
-
40
- CustomDataLink.connect(n1, n2, :data => 'foobar')
41
- link = CustomDataLink.find(:first, :conditions => { :ancestor_id => n1.id, :descendant_id => n2.id })
42
-
43
- assert_equal 'foobar', link.data
44
- end
45
-
46
- should 'return false if connection fails due to node invalidity' do
47
- n1 = ::Node.new
48
- n2 = ::Node.new
49
-
50
- n1.stubs(:valid?).returns(false)
51
-
52
- result = ::Link.connect(n1, n2)
53
- assert_equal false, result
54
- end
55
-
56
- should 'not save endpoints if connection fails due to node invalidity' do
57
- n1 = ::Node.new
58
- n2 = ::Node.new
59
-
60
- n1.stubs(:valid?).returns(false)
61
-
62
- ::Link.connect(n1, n2)
63
-
64
- assert n1.new_record?
65
- assert n2.new_record?
66
- end
67
- end
68
-
69
- context 'path?' do
70
- should 'return whether or not a path exists between two nodes' do
71
- n1 = ::Node.new
72
- n2 = ::Node.new
73
- n3 = ::Node.new
74
- n4 = ::Node.new
75
-
76
- ::Link.connect(n1, n2)
77
- ::Link.connect(n2, n3)
78
-
79
- assert ::Link.path?(n1, n2)
80
- assert ::Link.path?(n1, n3)
81
- assert !::Link.path?(n1, n4)
82
- end
83
- end
84
-
85
- context 'paths' do
86
- should 'return all paths between two nodes' do
87
- n1 = ::Node.new
88
- n2 = ::Node.new
89
- n3 = ::Node.new
90
-
91
- ::Link.connect(n1, n2)
92
- ::Link.connect(n2, n3)
93
-
94
- paths = ::Link.paths(n1, n3)
95
- assert_equal 1, paths.length
96
- assert_equal n1, paths.first.ancestor
97
- assert_equal n3, paths.first.descendant
98
- end
99
- end
100
- end
101
- end
102
- end
@@ -1,38 +0,0 @@
1
- require 'helper'
2
-
3
- module Dagnabit
4
- module Link
5
- class TestConfiguration < ActiveRecord::TestCase
6
- should 'have default and settable names for transitive closure model and column names' do
7
- default_model = Class.new(ActiveRecord::Base) do
8
- set_table_name 'edges'
9
-
10
- acts_as_dag_link
11
- end
12
-
13
- custom_model = Class.new(ActiveRecord::Base) do
14
- set_table_name 'other_name_edges'
15
-
16
- acts_as_dag_link :ancestor_id_column => 'the_ancestor_id',
17
- :descendant_id_column => 'the_descendant_id',
18
- :transitive_closure_table_name => 'my_transitive_closure',
19
- :transitive_closure_class_name => 'MyTransitiveClosureLink'
20
- end
21
-
22
- assert_equal 'ancestor_id', default_model.ancestor_id_column
23
- assert_equal 'descendant_id', default_model.descendant_id_column
24
- assert_equal default_model.connection.quote_table_name('edges_transitive_closure_tuples'), default_model.transitive_closure_table_name
25
- assert_equal 'TransitiveClosureLink', default_model.transitive_closure_class_name
26
-
27
- assert_equal 'the_ancestor_id', custom_model.ancestor_id_column
28
- assert_equal 'the_descendant_id', custom_model.descendant_id_column
29
- assert_equal custom_model.connection.quote_table_name('my_transitive_closure'), custom_model.transitive_closure_table_name
30
- assert_equal 'MyTransitiveClosureLink', custom_model.transitive_closure_class_name
31
- end
32
-
33
- should 'not have its configuration accessors on ActiveRecord::Base' do
34
- assert !ActiveRecord::Base.respond_to?(:ancestor_id_column)
35
- end
36
- end
37
- end
38
- end
@@ -1,64 +0,0 @@
1
- require 'helper'
2
-
3
- module Dagnabit
4
- module Link
5
- class TestCyclePrevention < ActiveRecord::TestCase
6
- should 'prevent simple cycles from being saved' do
7
- n1 = ::Node.create
8
- n2 = ::Node.create
9
-
10
- l1 = ::Link.create(:ancestor => n1, :descendant => n2)
11
- l2 = ::Link.create(:ancestor => n2, :descendant => n1)
12
-
13
- assert l2.new_record?
14
- end
15
-
16
- should 'prevent self-referential nodes' do
17
- n1 = ::Node.create
18
-
19
- l1 = ::Link.create(:ancestor => n1, :descendant => n1)
20
- assert l1.new_record?
21
- end
22
-
23
- should 'prevent cycles from being saved' do
24
- n1 = ::Node.create
25
- n2 = ::Node.create
26
- n3 = ::Node.create
27
- n4 = ::Node.create
28
-
29
- ::Link.create(:ancestor => n1, :descendant => n2)
30
- ::Link.create(:ancestor => n2, :descendant => n3)
31
- ::Link.create(:ancestor => n3, :descendant => n4)
32
- l = ::Link.create(:ancestor => n4, :descendant => n2)
33
-
34
- assert l.new_record?
35
- end
36
-
37
- should 'not prevent links from being saved multiple times in a row' do
38
- n1 = ::Node.create
39
- n2 = ::Node.create
40
-
41
- l = ::Link.new(:ancestor => n1, :descendant => n2)
42
-
43
- assert l.save
44
- assert l.save, 'should have been able to save twice'
45
- end
46
-
47
- should 'prevent cycles from being saved in customized links' do
48
- n1 = ::Node.create
49
- n2 = ::Node.create
50
- n3 = ::Node.create
51
-
52
- ::CustomizedLink.create(:ancestor => n1, :descendant => n2)
53
- ::CustomizedLink.create(:ancestor => n1, :descendant => n3)
54
- l3 = ::CustomizedLink.create(:ancestor => n3, :descendant => n1)
55
-
56
- assert l3.new_record?
57
- end
58
-
59
- should 'not execute on links that have no ancestor or descendant' do
60
- assert_nothing_raised { ::Link.create }
61
- end
62
- end
63
- end
64
- end
@@ -1,32 +0,0 @@
1
- require 'helper'
2
-
3
- module Dagnabit
4
- module Link
5
- class TestNamedScopes < ActiveRecord::TestCase
6
- class OtherNode < ActiveRecord::Base
7
- set_table_name 'nodes'
8
- end
9
-
10
- def setup
11
- @n1 = ::Node.new
12
- @n2 = OtherNode.new
13
- @n3 = ::Node.new
14
-
15
- @l1 = ::Link.build_edge(@n1, @n2)
16
- @l2 = ::Link.build_edge(@n2, @n3)
17
- @l1.save
18
- @l2.save
19
- end
20
-
21
- should 'scope links by ancestor type' do
22
- links = ::Link.ancestor_type(OtherNode.name)
23
- assert_equal [@l2], links
24
- end
25
-
26
- should 'scope links by descendant type' do
27
- links = ::Link.descendant_type(OtherNode.name)
28
- assert_equal [@l1], links
29
- end
30
- end
31
- end
32
- end
@@ -1,69 +0,0 @@
1
- require 'helper'
2
-
3
- module Dagnabit
4
- module Link
5
- class TestTransitiveClosureLinkModel < ActiveRecord::TestCase
6
- def setup
7
- @model = ::Link::TransitiveClosureLink.new
8
- @model.class.set_table_name 'edges_transitive_closure_tuples'
9
- @node = ::Node.new
10
- end
11
-
12
- should 'belong to an ancestor' do
13
- @model.ancestor = @node
14
- @model.save
15
-
16
- @model = ::Link::TransitiveClosureLink.find(@model.id)
17
- assert_equal @node, @model.ancestor
18
- end
19
-
20
- should 'belong to a descendant' do
21
- @model.descendant = @node
22
- @model.save
23
-
24
- @model = ::Link::TransitiveClosureLink.find(@model.id)
25
- assert_equal @node, @model.descendant
26
- end
27
-
28
- # TODO: wrap tests in transaction
29
- should 'support find(:all) queries including associations' do
30
- ::Link::TransitiveClosureLink.delete_all
31
-
32
- n1 = ::Node.new
33
- n2 = ::Node.new
34
- ::Link::TransitiveClosureLink.create(:ancestor => n1, :descendant => n2)
35
-
36
- links = ::Link::TransitiveClosureLink.find(:all, :include => :ancestor)
37
- assert_equal 1, links.length
38
- end
39
-
40
- should 'support scoping by ancestor type' do
41
- ::Link::TransitiveClosureLink.delete_all
42
-
43
- n1 = ::BetaNode.new
44
- n2 = ::Node.new
45
-
46
- ::Link::TransitiveClosureLink.create(:ancestor => n1, :descendant => n2)
47
-
48
- links = ::Link::TransitiveClosureLink.ancestor_type(::BetaNode.name)
49
-
50
- assert_equal 1, links.length
51
- assert_equal n1, links.first.ancestor
52
- end
53
-
54
- should 'support scoping by descendant type' do
55
- ::Link::TransitiveClosureLink.delete_all
56
-
57
- n1 = ::Node.new
58
- n2 = ::BetaNode.new
59
-
60
- ::Link::TransitiveClosureLink.create(:ancestor => n1, :descendant => n2)
61
-
62
- links = ::Link::TransitiveClosureLink.descendant_type(::BetaNode.name)
63
-
64
- assert_equal 1, links.length
65
- assert_equal n2, links.first.descendant
66
- end
67
- end
68
- end
69
- end
@@ -1,178 +0,0 @@
1
- require 'helper'
2
-
3
- module Dagnabit
4
- module Link
5
- class TestTransitiveClosureRecalculation < ActiveRecord::TestCase
6
- TransitiveClosureLink = ::Link::TransitiveClosureLink
7
- CustomTransitiveClosureLink = CustomizedLink::TransitiveClosureLink
8
- TransitiveClosureCustomDataLink = CustomDataLink::TransitiveClosureLink
9
-
10
- should 'recalculate transitive closure on create' do
11
- n1 = ::Node.create
12
- n2 = ::Node.create
13
- n3 = ::Node.create
14
-
15
- ::Link.create(:ancestor => n1, :descendant => n2)
16
- ::Link.create(:ancestor => n2, :descendant => n3)
17
-
18
- tc = TransitiveClosureLink.find(:first, :conditions => { :ancestor_id => n1.id, :descendant_id => n3.id })
19
- assert_not_nil tc, 'expected to find path from n1 to n3'
20
- end
21
-
22
- should 'transfer custom data attributes to transitive closure' do
23
- n1 = ::Node.create
24
- n2 = ::Node.create
25
- n3 = ::Node.create
26
-
27
- CustomDataLink.create(:ancestor => n1, :descendant => n2, :data => 'foo')
28
- CustomDataLink.create(:ancestor => n2, :descendant => n3, :data => 'bar')
29
-
30
- tc1 = TransitiveClosureCustomDataLink.find(:first, :conditions => { :ancestor_id => n1.id, :descendant_id => n2.id })
31
- tc2 = TransitiveClosureCustomDataLink.find(:first, :conditions => { :ancestor_id => n2.id, :descendant_id => n3.id })
32
- tc3 = TransitiveClosureCustomDataLink.find(:first, :conditions => { :ancestor_id => n1.id, :descendant_id => n3.id })
33
-
34
- assert_equal 'foo', tc1.data, 'expected to find custom data attribute on n1->n2 edge'
35
- assert_equal 'bar', tc2.data, 'expected to find custom data attribute on n2->n3 edge'
36
- assert_not_nil tc3, 'expected to find path from n1 to n3'
37
- assert_nil tc3.data, 'expected to find no custom data attribute on n1->n3 path'
38
- end
39
-
40
- should 'recalculate transitive closure on destroy' do
41
- n1 = ::Node.create
42
- n2 = ::Node.create
43
- n3 = ::Node.create
44
-
45
- l1 = ::Link.create(:ancestor => n1, :descendant => n2)
46
- l2 = ::Link.create(:ancestor => n2, :descendant => n3)
47
-
48
- l2.destroy
49
-
50
- tc = TransitiveClosureLink.find(:first, :conditions => { :ancestor_id => n1.id, :descendant_id => n2.id })
51
- assert_not_nil tc, 'expected to find path from n1 to n2'
52
-
53
- tc = TransitiveClosureLink.find(:first, :conditions => { :ancestor_id => n1.id, :descendant_id => n3.id })
54
- assert_nil tc, 'expected to not find path from n1 to n3'
55
- end
56
-
57
- should 'recalculate transitive closure when destroying links with custom data' do
58
- n1 = ::Node.create
59
- n2 = ::Node.create
60
- n3 = ::Node.create
61
- n4 = ::Node.create
62
-
63
- l1 = CustomDataLink.create(:ancestor => n1, :descendant => n2, :data => 'foo')
64
- l2 = CustomDataLink.create(:ancestor => n2, :descendant => n3, :data => 'bar')
65
- l3 = CustomDataLink.create(:ancestor => n3, :descendant => n4, :data => 'baz')
66
-
67
- l2.destroy
68
-
69
- tc1 = TransitiveClosureCustomDataLink.find(:first, :conditions => { :ancestor_id => n1.id, :descendant_id => n2.id })
70
- assert_not_nil tc1, 'expected to find path from n1 to n2'
71
- assert_equal 'foo', tc1.data, 'expected to find custom data attribute on n1->n2 edge'
72
-
73
- tc2 = TransitiveClosureCustomDataLink.find(:first, :conditions => { :ancestor_id => n3.id, :descendant_id => n4.id })
74
- assert_not_nil tc2, 'expected to find path from n3 to n4'
75
- assert_equal 'baz', tc2.data, 'expected to find custom data attribute on n3->n4 edge'
76
-
77
- tc = TransitiveClosureCustomDataLink.find(:first, :conditions => { :ancestor_id => n1.id, :descendant_id => n3.id })
78
- assert_nil tc, 'expected to not find path from n1 to n3'
79
- tc = TransitiveClosureCustomDataLink.find(:first, :conditions => { :ancestor_id => n2.id, :descendant_id => n4.id })
80
- assert_nil tc, 'expected to not find path from n2 to n4'
81
- tc = TransitiveClosureCustomDataLink.find(:first, :conditions => { :ancestor_id => n1.id, :descendant_id => n4.id })
82
- assert_nil tc, 'expected to not find path from n1 to n4'
83
- end
84
-
85
- should 'include edges in the graph when reconstructing the transitive closure on destroy' do
86
- n1 = ::Node.create
87
- n2 = ::Node.create
88
- n3 = ::Node.create
89
-
90
- l1 = ::Link.create(:ancestor => n1, :descendant => n2)
91
- l2 = ::Link.create(:ancestor => n2, :descendant => n3)
92
- l3 = ::Link.create(:ancestor => n1, :descendant => n3)
93
-
94
- l1.destroy
95
- l2.destroy
96
-
97
- tc = TransitiveClosureLink.find(:first, :conditions => { :ancestor_id => n1.id, :descendant_id => n3.id })
98
- assert_not_nil tc, 'expected to find path from n1 to n3'
99
- end
100
-
101
- should 'recalculate transitive closure on update' do
102
- n1 = ::Node.create
103
- n2 = ::Node.create
104
- n3 = ::Node.create
105
- n4 = ::Node.create
106
-
107
- l1 = ::Link.create(:ancestor => n1, :descendant => n2)
108
- l2 = ::Link.create(:ancestor => n2, :descendant => n3)
109
-
110
- l2.update_attribute(:descendant, n4)
111
-
112
- tc = TransitiveClosureLink.find(:first, :conditions => { :ancestor_id => n1.id, :descendant_id => n4.id })
113
- assert_not_nil tc, 'expected to find path from n1 to n4'
114
-
115
- tc = TransitiveClosureLink.find(:first, :conditions => { :ancestor_id => n1.id, :descendant_id => n3.id })
116
- assert_nil tc, 'expected to not find path from n1 to n3'
117
- end
118
-
119
- should 'recalculate transitive closure on create using custom-configured link' do
120
- n1 = ::Node.create
121
- n2 = ::Node.create
122
- n3 = ::Node.create
123
-
124
- CustomizedLink.create(:ancestor => n1, :descendant => n2)
125
- CustomizedLink.create(:ancestor => n2, :descendant => n3)
126
-
127
- tc = CustomTransitiveClosureLink.find(:first, :conditions => { :the_ancestor_id => n1.id, :the_descendant_id => n3.id })
128
- assert_not_nil tc, 'expected to find path from n1 to n3'
129
- end
130
-
131
- should 'recalculate transitive closure on destroy using custom-configured link' do
132
- n1 = ::Node.create
133
- n2 = ::Node.create
134
- n3 = ::Node.create
135
-
136
- l1 = CustomizedLink.create(:ancestor => n1, :descendant => n2)
137
- l2 = CustomizedLink.create(:ancestor => n2, :descendant => n3)
138
-
139
- l2.destroy
140
-
141
- tc = CustomTransitiveClosureLink.find(:first, :conditions => { :the_ancestor_id => n1.id, :the_descendant_id => n2.id })
142
- assert_not_nil tc, 'expected to find path from n1 to n2'
143
-
144
- tc = CustomTransitiveClosureLink.find(:first, :conditions => { :the_ancestor_id => n1.id, :the_descendant_id => n3.id })
145
- assert_nil tc, 'expected to not find path from n1 to n3'
146
- end
147
-
148
- should 'recalculate transitive closure on update using custom-configured link' do
149
- n1 = ::Node.create
150
- n2 = ::Node.create
151
- n3 = ::Node.create
152
- n4 = ::Node.create
153
-
154
- l1 = CustomizedLink.create(:ancestor => n1, :descendant => n2)
155
- l2 = CustomizedLink.create(:ancestor => n2, :descendant => n3)
156
-
157
- l2.update_attribute(:descendant, n4)
158
-
159
- tc = CustomTransitiveClosureLink.find(:first, :conditions => { :the_ancestor_id => n1.id, :the_descendant_id => n4.id })
160
- assert_not_nil tc, 'expected to find path from n1 to n4'
161
-
162
- tc = CustomTransitiveClosureLink.find(:first, :conditions => { :the_ancestor_id => n1.id, :the_descendant_id => n3.id })
163
- assert_nil tc, 'expected to not find path from n1 to n3'
164
- end
165
-
166
- should "not recalculate transitive closure if neither a link's source nor target changed" do
167
- n1 = ::Node.create
168
- n2 = ::Node.create
169
-
170
- l1 = ::Link.new(:ancestor => n1, :descendant => n2)
171
-
172
- l1.expects(:update_transitive_closure_for_destroy).never
173
- l1.save
174
- l1.save
175
- end
176
- end
177
- end
178
- end