ramdiv-mongo_mapper_acts_as_tree 0.0.5 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +3 -2
- data/VERSION +1 -1
- data/lib/mongo_mapper_acts_as_tree.rb +24 -9
- data/ramdiv-mongo_mapper_acts_as_tree.gemspec +6 -2
- data/test/helper.rb +3 -5
- data/test/models/shapes.rb +14 -0
- data/test/test_search_class.rb +90 -0
- data/test/test_tree.rb +3 -3
- metadata +7 -3
data/README.rdoc
CHANGED
@@ -21,12 +21,13 @@ Enable the tree functionality by declaring acts_as_tree on your model
|
|
21
21
|
acts_as_tree
|
22
22
|
end
|
23
23
|
|
24
|
-
The method accepts :parent_id_field, :path_field, :depth_field, :order as a hash.
|
24
|
+
The method accepts :parent_id_field, :path_field, :depth_field, :order, :search_class as a hash.
|
25
25
|
|
26
26
|
:parent_id_field, :path_field, :depth_field => override the default field names
|
27
27
|
:order => control the order (format "_field-name_ _[asc|desc]_")
|
28
|
+
:search_class => expects a Class that is a MongoMapper::Document to be used for search
|
28
29
|
|
29
|
-
Check
|
30
|
+
Check test_tree.rb and test_search_class.rb for examples.
|
30
31
|
|
31
32
|
== About bugs
|
32
33
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0
|
1
|
+
0.1.0
|
@@ -49,7 +49,7 @@ module MongoMapper
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def parent=(var)
|
52
|
-
var =
|
52
|
+
var = search_class.find(var) if var.is_a? String
|
53
53
|
|
54
54
|
if self.descendants.include? var
|
55
55
|
@_cyclic = true
|
@@ -79,7 +79,7 @@ module MongoMapper
|
|
79
79
|
end
|
80
80
|
|
81
81
|
def parent
|
82
|
-
@_parent or (self[parent_id_field].nil? ? nil :
|
82
|
+
@_parent or (self[parent_id_field].nil? ? nil : search_class.find(self[parent_id_field]))
|
83
83
|
end
|
84
84
|
|
85
85
|
def root?
|
@@ -87,12 +87,12 @@ module MongoMapper
|
|
87
87
|
end
|
88
88
|
|
89
89
|
def root
|
90
|
-
self[path_field].first.nil? ? self :
|
90
|
+
self[path_field].first.nil? ? self : search_class.find(self[path_field].first)
|
91
91
|
end
|
92
92
|
|
93
93
|
def ancestors
|
94
94
|
return [] if root?
|
95
|
-
|
95
|
+
search_class.find(self[path_field])
|
96
96
|
end
|
97
97
|
|
98
98
|
def self_and_ancestors
|
@@ -100,20 +100,20 @@ module MongoMapper
|
|
100
100
|
end
|
101
101
|
|
102
102
|
def siblings
|
103
|
-
|
103
|
+
search_class.all(:_id => {"$ne" => self._id}, parent_id_field => self[parent_id_field], :order => tree_order)
|
104
104
|
end
|
105
105
|
|
106
106
|
def self_and_siblings
|
107
|
-
|
107
|
+
search_class.all(parent_id_field => self[parent_id_field], :order => tree_order)
|
108
108
|
end
|
109
109
|
|
110
110
|
def children
|
111
|
-
|
111
|
+
search_class.all(parent_id_field => self._id, :order => tree_order)
|
112
112
|
end
|
113
113
|
|
114
114
|
def descendants
|
115
115
|
return [] if new_record?
|
116
|
-
|
116
|
+
search_class.all(path_field => self._id, :order => tree_order)
|
117
117
|
end
|
118
118
|
|
119
119
|
def self_and_descendants
|
@@ -156,7 +156,7 @@ module MongoMapper
|
|
156
156
|
end
|
157
157
|
|
158
158
|
def destroy_descendants
|
159
|
-
|
159
|
+
search_class.destroy(self.descendants.map(&:_id))
|
160
160
|
end
|
161
161
|
end
|
162
162
|
|
@@ -176,6 +176,21 @@ module MongoMapper
|
|
176
176
|
def tree_order
|
177
177
|
acts_as_tree_options[:order] or ""
|
178
178
|
end
|
179
|
+
|
180
|
+
# When added as an option to acts_as_tree, search class will be used as the base from which to
|
181
|
+
# find tree objects. This is handy should you have a tree of objects that are of different types, but
|
182
|
+
# might be related through single table inheritance.
|
183
|
+
#
|
184
|
+
# acts_as_tree :search_class => Shape
|
185
|
+
#
|
186
|
+
# In the above example, you could have a working tree ofShape, Circle and Square types (assuming
|
187
|
+
# Circle and Square were subclasses of Shape). If you want to do the same thing and you don't provide
|
188
|
+
# search_class, nesting mixed types will not work.
|
189
|
+
#
|
190
|
+
# The default is +self.class+
|
191
|
+
def search_class
|
192
|
+
acts_as_tree_options[:search_class] or self.class
|
193
|
+
end
|
179
194
|
end
|
180
195
|
end
|
181
196
|
end
|
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{ramdiv-mongo_mapper_acts_as_tree}
|
8
|
-
s.version = "0.0
|
8
|
+
s.version = "0.1.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Jakob Vidmar"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-06-05}
|
13
13
|
s.description = %q{Port of the old, venerable ActsAsTree with a bit of a twist}
|
14
14
|
s.email = %q{jakob.vidmar@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -28,7 +28,9 @@ Gem::Specification.new do |s|
|
|
28
28
|
"test/helper.rb",
|
29
29
|
"test/models/category.rb",
|
30
30
|
"test/models/ordered_category.rb",
|
31
|
+
"test/models/shapes.rb",
|
31
32
|
"test/test_order.rb",
|
33
|
+
"test/test_search_class.rb",
|
32
34
|
"test/test_tree.rb"
|
33
35
|
]
|
34
36
|
s.homepage = %q{http://github.com/ramdiv/mongo_mapper_acts_as_tree}
|
@@ -40,7 +42,9 @@ Gem::Specification.new do |s|
|
|
40
42
|
"test/helper.rb",
|
41
43
|
"test/models/category.rb",
|
42
44
|
"test/models/ordered_category.rb",
|
45
|
+
"test/models/shapes.rb",
|
43
46
|
"test/test_order.rb",
|
47
|
+
"test/test_search_class.rb",
|
44
48
|
"test/test_tree.rb"
|
45
49
|
]
|
46
50
|
|
data/test/helper.rb
CHANGED
@@ -11,11 +11,9 @@ MongoMapper.database = "acts_as_tree-test"
|
|
11
11
|
Dir["#{File.dirname(__FILE__)}/models/*.rb"].each {|file| require file}
|
12
12
|
|
13
13
|
class Test::Unit::TestCase
|
14
|
-
# Drop all
|
15
|
-
|
16
|
-
MongoMapper.database.collections.each
|
17
|
-
coll.remove
|
18
|
-
end
|
14
|
+
# Drop all collections after each test case.
|
15
|
+
def teardown
|
16
|
+
MongoMapper.database.collections.each {|collection| collection.drop }
|
19
17
|
end
|
20
18
|
|
21
19
|
# Make sure that each test case has a teardown
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "mongo_mapper"
|
2
|
+
require "mongo_mapper_acts_as_tree"
|
3
|
+
|
4
|
+
class Shape
|
5
|
+
include MongoMapper::Document
|
6
|
+
include MongoMapper::Acts::Tree
|
7
|
+
|
8
|
+
key :name, String
|
9
|
+
|
10
|
+
acts_as_tree :search_class => Shape
|
11
|
+
end
|
12
|
+
|
13
|
+
class Circle < Shape; end
|
14
|
+
class Square < Shape; end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestSearchScope < Test::Unit::TestCase
|
4
|
+
context "Simple, mixed type tree" do
|
5
|
+
setup do
|
6
|
+
shape = Shape.create(:name => "Root")
|
7
|
+
Circle.create(:name => "Circle", :parent => shape)
|
8
|
+
Square.create(:name => "Square", :parent => shape)
|
9
|
+
end
|
10
|
+
|
11
|
+
setup do
|
12
|
+
# We are loading from the database here because this process proves the point. If we never did it this
|
13
|
+
# way, there would be no reason to change the code.
|
14
|
+
@shape, @circle, @square = Shape.first, Circle.first, Square.first
|
15
|
+
end
|
16
|
+
|
17
|
+
should "return circle and square as children of shape" do
|
18
|
+
assert_equal [@circle, @square], @shape.children
|
19
|
+
end
|
20
|
+
|
21
|
+
should("return shape as parent of circle") { assert_equal @shape, @circle.parent }
|
22
|
+
should("return shape as parent of square") { assert_equal @shape, @square.parent }
|
23
|
+
|
24
|
+
should("return square as exclusive sibling of circle") { assert_equal [@square], @circle.siblings }
|
25
|
+
should "return self and square as inclusive siblings of circle" do
|
26
|
+
assert_equal [@circle, @square], @circle.self_and_siblings
|
27
|
+
end
|
28
|
+
|
29
|
+
should("return circle as exclusive sibling of square") { assert_equal [@circle], @square.siblings }
|
30
|
+
should "return self and circle as inclusive siblings of square" do
|
31
|
+
assert_equal [@circle, @square], @square.self_and_siblings
|
32
|
+
end
|
33
|
+
|
34
|
+
should "return circle and square as exclusive descendants of shape" do
|
35
|
+
assert_equal [@circle, @square], @shape.descendants
|
36
|
+
end
|
37
|
+
should "return shape, circle and square as inclusive descendants of shape" do
|
38
|
+
assert_equal [@shape, @circle, @square], @shape.self_and_descendants
|
39
|
+
end
|
40
|
+
|
41
|
+
should("return shape as exclusive ancestor of circle") { assert_equal [@shape], @circle.ancestors }
|
42
|
+
should "return self and shape as inclusive ancestors of circle" do
|
43
|
+
assert_equal [@shape, @circle], @circle.self_and_ancestors
|
44
|
+
end
|
45
|
+
|
46
|
+
should("return shape as exclusive ancestor of square") { assert_equal [@shape], @square.ancestors }
|
47
|
+
should "return self and shape as inclusive ancestors of square" do
|
48
|
+
assert_equal [@shape, @square], @square.self_and_ancestors
|
49
|
+
end
|
50
|
+
|
51
|
+
should("return shape as root of circle") { assert_equal @shape, @square.root }
|
52
|
+
should("return shape as root of square") { assert_equal @shape, @circle.root }
|
53
|
+
end
|
54
|
+
|
55
|
+
context "A tree with mixed types on either side of a branch" do
|
56
|
+
setup do
|
57
|
+
shape = Shape.create(:name => "Root")
|
58
|
+
circle = Circle.create(:name => "Circle", :parent => shape)
|
59
|
+
Square.create(:name => "Square", :parent => circle)
|
60
|
+
end
|
61
|
+
|
62
|
+
setup do
|
63
|
+
@shape, @circle, @square = Shape.first, Circle.first, Square.first
|
64
|
+
end
|
65
|
+
|
66
|
+
should("return circle as child of shape") { assert_equal [@circle], @shape.children }
|
67
|
+
should("return square as child of circle") { assert_equal [@square], @circle.children }
|
68
|
+
should("return circle as parent of square") { assert_equal @circle, @square.parent }
|
69
|
+
should("return shape as parent of circle") { assert_equal @shape, @circle.parent }
|
70
|
+
|
71
|
+
should "return circle and square as descendants of shape" do
|
72
|
+
assert_equal [@circle, @square], @shape.descendants
|
73
|
+
end
|
74
|
+
|
75
|
+
should("return square as descendant of circle") { assert_equal [@square], @circle.descendants }
|
76
|
+
|
77
|
+
should "return shape and circle as ancestors of square" do
|
78
|
+
assert_equal [@shape, @circle], @square.ancestors
|
79
|
+
end
|
80
|
+
|
81
|
+
should("return shape as ancestor of circle") { assert_equal [@shape], @circle.ancestors }
|
82
|
+
|
83
|
+
should "destroy descendants of shape" do
|
84
|
+
@shape.destroy_descendants
|
85
|
+
assert_nil Shape.find(@circle._id)
|
86
|
+
assert_nil Shape.find(@square._id)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
end # TestSearchScope
|
data/test/test_tree.rb
CHANGED
@@ -12,9 +12,9 @@ class TestMongomapperActsAsTree < Test::Unit::TestCase
|
|
12
12
|
@root_2 = Category.create(:name => "Root 2")
|
13
13
|
end
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
should "create node from id " do
|
16
|
+
assert Category.create(:name => "Child 2.2", :parent => @root_1.id.to_s).parent == @root_1
|
17
|
+
end
|
18
18
|
|
19
19
|
should "have roots" do
|
20
20
|
assert eql_arrays?(Category.roots, [@root_1, @root_2])
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
+
- 1
|
7
8
|
- 0
|
8
|
-
|
9
|
-
version: 0.0.5
|
9
|
+
version: 0.1.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Jakob Vidmar
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-06-05 00:00:00 +02:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -66,7 +66,9 @@ files:
|
|
66
66
|
- test/helper.rb
|
67
67
|
- test/models/category.rb
|
68
68
|
- test/models/ordered_category.rb
|
69
|
+
- test/models/shapes.rb
|
69
70
|
- test/test_order.rb
|
71
|
+
- test/test_search_class.rb
|
70
72
|
- test/test_tree.rb
|
71
73
|
has_rdoc: true
|
72
74
|
homepage: http://github.com/ramdiv/mongo_mapper_acts_as_tree
|
@@ -102,5 +104,7 @@ test_files:
|
|
102
104
|
- test/helper.rb
|
103
105
|
- test/models/category.rb
|
104
106
|
- test/models/ordered_category.rb
|
107
|
+
- test/models/shapes.rb
|
105
108
|
- test/test_order.rb
|
109
|
+
- test/test_search_class.rb
|
106
110
|
- test/test_tree.rb
|