mongoid-tree 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +2 -1
- data/lib/mongoid/tree.rb +3 -3
- data/lib/mongoid/tree/ordering.rb +51 -40
- data/spec/mongoid/tree/ordering_spec.rb +93 -79
- data/spec/mongoid/tree/traversal_spec.rb +22 -22
- data/spec/mongoid/tree_spec.rb +106 -80
- data/spec/spec_helper.rb +3 -0
- metadata +13 -23
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 839d3ab28af5b3c0b2c9d4050f1c6940c444bd29
|
4
|
+
data.tar.gz: c9d5033394a48416907f5500fa990b8bf6d96f6e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a85f4ac7c49b858afd70a696aa0595df7af63ae85f21b15330cc3b88b3e277ee30cec3f1fe43dad34246126d3dec8f1da701a162430878f0ae30ef363e569696
|
7
|
+
data.tar.gz: 458d20a30a99b0940c882e14bc080b5c2efaeedbc90f92cc28eae56ee835795194f8695d3c9c9a55e5f0e6977a4ef7eec97d19860b845b9f3656b15d475848f1
|
data/Gemfile
CHANGED
data/lib/mongoid/tree.rb
CHANGED
@@ -103,7 +103,7 @@ module Mongoid
|
|
103
103
|
end
|
104
104
|
|
105
105
|
##
|
106
|
-
# This module implements class methods that will be available
|
106
|
+
# This module implements class methods that will be available
|
107
107
|
# on the document that includes Mongoid::Tree
|
108
108
|
module ClassMethods
|
109
109
|
|
@@ -213,7 +213,7 @@ module Mongoid
|
|
213
213
|
# @note Generated by Mongoid
|
214
214
|
#
|
215
215
|
# @param [Mongoid::Tree] document
|
216
|
-
|
216
|
+
|
217
217
|
##
|
218
218
|
# @!method parent_ids
|
219
219
|
# Returns a list of the document's parent_ids, starting with the root node.
|
@@ -272,7 +272,7 @@ module Mongoid
|
|
272
272
|
#
|
273
273
|
# @return [Mongoid::Criteria] Mongoid criteria to retrieve the documents ancestors
|
274
274
|
def ancestors
|
275
|
-
base_class.
|
275
|
+
base_class.or(parent_ids.map { |id| { :_id => id } })
|
276
276
|
end
|
277
277
|
|
278
278
|
##
|
@@ -37,7 +37,7 @@ module Mongoid
|
|
37
37
|
|
38
38
|
default_scope asc(:position)
|
39
39
|
|
40
|
-
before_save :assign_default_position
|
40
|
+
before_save :assign_default_position, :if => :assign_default_position?
|
41
41
|
before_save :reposition_former_siblings, :if => :sibling_reposition_required?
|
42
42
|
after_destroy :move_lower_siblings_up
|
43
43
|
end
|
@@ -45,29 +45,39 @@ module Mongoid
|
|
45
45
|
##
|
46
46
|
# Returns a chainable criteria for this document's ancestors
|
47
47
|
#
|
48
|
-
# @return [Mongoid::Criteria] Mongoid criteria to retrieve the
|
48
|
+
# @return [Mongoid::Criteria] Mongoid criteria to retrieve the document's ancestors
|
49
49
|
def ancestors
|
50
|
-
base_class.unscoped
|
50
|
+
base_class.unscoped { super }
|
51
51
|
end
|
52
52
|
|
53
53
|
##
|
54
54
|
# Returns siblings below the current document.
|
55
|
-
# Siblings with a position greater than this
|
55
|
+
# Siblings with a position greater than this document's position.
|
56
56
|
#
|
57
|
-
# @return [Mongoid::Criteria] Mongoid criteria to retrieve the
|
57
|
+
# @return [Mongoid::Criteria] Mongoid criteria to retrieve the document's lower siblings
|
58
58
|
def lower_siblings
|
59
59
|
self.siblings.where(:position.gt => self.position)
|
60
60
|
end
|
61
61
|
|
62
62
|
##
|
63
63
|
# Returns siblings above the current document.
|
64
|
-
# Siblings with a position lower than this
|
64
|
+
# Siblings with a position lower than this document's position.
|
65
65
|
#
|
66
|
-
# @return [Mongoid::Criteria] Mongoid criteria to retrieve the
|
66
|
+
# @return [Mongoid::Criteria] Mongoid criteria to retrieve the document's higher siblings
|
67
67
|
def higher_siblings
|
68
68
|
self.siblings.where(:position.lt => self.position)
|
69
69
|
end
|
70
70
|
|
71
|
+
##
|
72
|
+
# Returns siblings between the current document and the other document
|
73
|
+
# Siblings with a position between this document's position and the other document's position.
|
74
|
+
#
|
75
|
+
# @return [Mongoid::Criteria] Mongoid criteria to retrieve the documents between this and the other document
|
76
|
+
def siblings_between(other)
|
77
|
+
range = [self.position, other.position].sort
|
78
|
+
self.siblings.where(:position.gt => range.first, :position.lt => range.last)
|
79
|
+
end
|
80
|
+
|
71
81
|
##
|
72
82
|
# Returns the lowest sibling (could be self)
|
73
83
|
#
|
@@ -123,9 +133,7 @@ module Mongoid
|
|
123
133
|
#
|
124
134
|
# @return [undefined]
|
125
135
|
def move_up
|
126
|
-
|
127
|
-
siblings.where(:position => self.position - 1).first.inc(:position, 1)
|
128
|
-
inc(:position, -1)
|
136
|
+
switch_with_sibling_at_offset(-1) unless at_top?
|
129
137
|
end
|
130
138
|
|
131
139
|
##
|
@@ -133,9 +141,7 @@ module Mongoid
|
|
133
141
|
#
|
134
142
|
# @return [undefined]
|
135
143
|
def move_down
|
136
|
-
|
137
|
-
siblings.where(:position => self.position + 1).first.inc(:position, -1)
|
138
|
-
inc(:position, 1)
|
144
|
+
switch_with_sibling_at_offset(1) unless at_bottom?
|
139
145
|
end
|
140
146
|
|
141
147
|
##
|
@@ -147,23 +153,19 @@ module Mongoid
|
|
147
153
|
#
|
148
154
|
# @return [undefined]
|
149
155
|
def move_above(other)
|
150
|
-
|
151
|
-
self.parent_id = other.parent_id
|
152
|
-
save!
|
153
|
-
end
|
156
|
+
ensure_to_be_sibling_of(other)
|
154
157
|
|
155
158
|
if position > other.position
|
156
159
|
new_position = other.position
|
157
|
-
|
160
|
+
self.siblings_between(other).inc(:position, 1)
|
158
161
|
other.inc(:position, 1)
|
159
|
-
self.position = new_position
|
160
|
-
save!
|
161
162
|
else
|
162
163
|
new_position = other.position - 1
|
163
|
-
|
164
|
-
self.position = new_position
|
165
|
-
save!
|
164
|
+
self.siblings_between(other).inc(:position, -1)
|
166
165
|
end
|
166
|
+
|
167
|
+
self.position = new_position
|
168
|
+
save!
|
167
169
|
end
|
168
170
|
|
169
171
|
##
|
@@ -175,36 +177,43 @@ module Mongoid
|
|
175
177
|
#
|
176
178
|
# @return [undefined]
|
177
179
|
def move_below(other)
|
178
|
-
|
179
|
-
self.parent_id = other.parent_id
|
180
|
-
save!
|
181
|
-
end
|
180
|
+
ensure_to_be_sibling_of(other)
|
182
181
|
|
183
182
|
if position > other.position
|
184
183
|
new_position = other.position + 1
|
185
|
-
|
186
|
-
self.position = new_position
|
187
|
-
save!
|
184
|
+
self.siblings_between(other).inc(:position, 1)
|
188
185
|
else
|
189
186
|
new_position = other.position
|
190
|
-
|
187
|
+
self.siblings_between(other).inc(:position, -1)
|
191
188
|
other.inc(:position, -1)
|
192
|
-
self.position = new_position
|
193
|
-
save!
|
194
189
|
end
|
190
|
+
|
191
|
+
self.position = new_position
|
192
|
+
save!
|
195
193
|
end
|
196
194
|
|
197
195
|
private
|
198
196
|
|
197
|
+
def switch_with_sibling_at_offset(offset)
|
198
|
+
siblings.where(:position => self.position + offset).first.inc(:position, -offset)
|
199
|
+
inc(:position, offset)
|
200
|
+
end
|
201
|
+
|
202
|
+
def ensure_to_be_sibling_of(other)
|
203
|
+
return if sibling_of?(other)
|
204
|
+
self.parent_id = other.parent_id
|
205
|
+
save!
|
206
|
+
end
|
207
|
+
|
199
208
|
def move_lower_siblings_up
|
200
|
-
lower_siblings.
|
209
|
+
lower_siblings.inc(:position, -1)
|
201
210
|
end
|
202
211
|
|
203
212
|
def reposition_former_siblings
|
204
213
|
former_siblings = base_class.where(:parent_id => attribute_was('parent_id')).
|
205
214
|
and(:position.gt => (attribute_was('position') || 0)).
|
206
215
|
excludes(:id => self.id)
|
207
|
-
former_siblings.
|
216
|
+
former_siblings.inc(:position, -1)
|
208
217
|
end
|
209
218
|
|
210
219
|
def sibling_reposition_required?
|
@@ -212,14 +221,16 @@ module Mongoid
|
|
212
221
|
end
|
213
222
|
|
214
223
|
def assign_default_position
|
215
|
-
|
216
|
-
|
217
|
-
if self.siblings.empty? || self.siblings.collect(&:position).compact.empty?
|
218
|
-
self.position = 0
|
224
|
+
self.position = if self.siblings.where(:position.ne => nil).any?
|
225
|
+
self.last_sibling_in_list.position + 1
|
219
226
|
else
|
220
|
-
|
227
|
+
0
|
221
228
|
end
|
222
229
|
end
|
230
|
+
|
231
|
+
def assign_default_position?
|
232
|
+
self.position.nil? || self.parent_id_changed?
|
233
|
+
end
|
223
234
|
end
|
224
235
|
end
|
225
236
|
end
|
@@ -6,9 +6,9 @@ describe Mongoid::Tree::Ordering do
|
|
6
6
|
|
7
7
|
it "should store position as an Integer with a default of nil" do
|
8
8
|
f = OrderedNode.fields['position']
|
9
|
-
f.
|
10
|
-
f.options[:type].
|
11
|
-
f.options[:default].
|
9
|
+
expect(f).not_to be_nil
|
10
|
+
expect(f.options[:type]).to eq(Integer)
|
11
|
+
expect(f.options[:default]).not_to be
|
12
12
|
end
|
13
13
|
|
14
14
|
describe 'when saved' do
|
@@ -25,48 +25,48 @@ describe Mongoid::Tree::Ordering do
|
|
25
25
|
end
|
26
26
|
|
27
27
|
it "should assign a default position of 0 to each node without a sibling" do
|
28
|
-
node(:child).position.
|
29
|
-
node(:subchild).position.
|
30
|
-
node(:subsubchild).position.
|
28
|
+
expect(node(:child).position).to eq(0)
|
29
|
+
expect(node(:subchild).position).to eq(0)
|
30
|
+
expect(node(:subsubchild).position).to eq(0)
|
31
31
|
end
|
32
32
|
|
33
33
|
it "should place siblings at the end of the list by default" do
|
34
|
-
node(:root).position.
|
35
|
-
node(:other_root).position.
|
36
|
-
node(:other_child).position.
|
37
|
-
node(:another_child).position.
|
34
|
+
expect(node(:root).position).to eq(0)
|
35
|
+
expect(node(:other_root).position).to eq(1)
|
36
|
+
expect(node(:other_child).position).to eq(0)
|
37
|
+
expect(node(:another_child).position).to eq(1)
|
38
38
|
end
|
39
39
|
|
40
40
|
it "should move a node to the end of a list when it is moved to a new parent" do
|
41
41
|
other_root = node(:other_root)
|
42
42
|
child = node(:child)
|
43
|
-
child.position.
|
43
|
+
expect(child.position).to eq(0)
|
44
44
|
other_root.children << child
|
45
45
|
child.reload
|
46
|
-
child.position.
|
46
|
+
expect(child.position).to eq(2)
|
47
47
|
end
|
48
48
|
|
49
49
|
it "should correctly reposition siblings when one of them is removed" do
|
50
50
|
node(:other_child).destroy
|
51
|
-
node(:another_child).position.
|
51
|
+
expect(node(:another_child).position).to eq(0)
|
52
52
|
end
|
53
53
|
|
54
54
|
it "should correctly reposition siblings when one of them is added to another parent" do
|
55
55
|
node(:root).children << node(:other_child)
|
56
|
-
node(:another_child).position.
|
56
|
+
expect(node(:another_child).position).to eq(0)
|
57
57
|
end
|
58
58
|
|
59
59
|
it "should correctly reposition siblings when the parent is changed" do
|
60
60
|
other_child = node(:other_child)
|
61
61
|
other_child.parent = node(:root)
|
62
62
|
other_child.save!
|
63
|
-
node(:another_child).position.
|
63
|
+
expect(node(:another_child).position).to eq(0)
|
64
64
|
end
|
65
65
|
|
66
66
|
it "should not reposition siblings when it's not yet saved" do
|
67
67
|
new_node = OrderedNode.new(:name => 'new')
|
68
68
|
new_node.parent = node(:root)
|
69
|
-
new_node.
|
69
|
+
expect(new_node).not_to receive(:reposition_former_siblings)
|
70
70
|
new_node.save
|
71
71
|
end
|
72
72
|
end
|
@@ -85,8 +85,8 @@ describe Mongoid::Tree::Ordering do
|
|
85
85
|
describe ':move_children_to_parent' do
|
86
86
|
it "should set its childen's parent_id to the documents parent_id" do
|
87
87
|
node(:child).move_children_to_parent
|
88
|
-
node(:child).
|
89
|
-
node(:root).children.to_a.
|
88
|
+
expect(node(:child)).to be_leaf
|
89
|
+
expect(node(:root).children.to_a).to eq([node(:child), node(:other_child), node(:subchild)])
|
90
90
|
end
|
91
91
|
end
|
92
92
|
end
|
@@ -105,68 +105,68 @@ describe Mongoid::Tree::Ordering do
|
|
105
105
|
describe '#lower_siblings' do
|
106
106
|
it "should return a collection of siblings lower on the list" do
|
107
107
|
node(:second_child_of_first_root).reload
|
108
|
-
node(:first_root).lower_siblings.to_a.
|
109
|
-
node(:second_root).lower_siblings.to_a.
|
110
|
-
node(:third_root).lower_siblings.to_a.
|
111
|
-
node(:first_child_of_first_root).lower_siblings.to_a.
|
112
|
-
node(:second_child_of_first_root).lower_siblings.to_a.
|
108
|
+
expect(node(:first_root).lower_siblings.to_a).to eq([node(:second_root), node(:third_root)])
|
109
|
+
expect(node(:second_root).lower_siblings.to_a).to eq([node(:third_root)])
|
110
|
+
expect(node(:third_root).lower_siblings.to_a).to eq([])
|
111
|
+
expect(node(:first_child_of_first_root).lower_siblings.to_a).to eq([node(:second_child_of_first_root)])
|
112
|
+
expect(node(:second_child_of_first_root).lower_siblings.to_a).to eq([])
|
113
113
|
end
|
114
114
|
end
|
115
115
|
|
116
116
|
describe '#higher_siblings' do
|
117
117
|
it "should return a collection of siblings lower on the list" do
|
118
|
-
node(:first_root).higher_siblings.to_a.
|
119
|
-
node(:second_root).higher_siblings.to_a.
|
120
|
-
node(:third_root).higher_siblings.to_a.
|
121
|
-
node(:first_child_of_first_root).higher_siblings.to_a.
|
122
|
-
node(:second_child_of_first_root).higher_siblings.to_a.
|
118
|
+
expect(node(:first_root).higher_siblings.to_a).to eq([])
|
119
|
+
expect(node(:second_root).higher_siblings.to_a).to eq([node(:first_root)])
|
120
|
+
expect(node(:third_root).higher_siblings.to_a).to eq([node(:first_root), node(:second_root)])
|
121
|
+
expect(node(:first_child_of_first_root).higher_siblings.to_a).to eq([])
|
122
|
+
expect(node(:second_child_of_first_root).higher_siblings.to_a).to eq([node(:first_child_of_first_root)])
|
123
123
|
end
|
124
124
|
end
|
125
125
|
|
126
126
|
describe '#at_top?' do
|
127
127
|
it "should return true when the node is first in the list" do
|
128
|
-
node(:first_root).
|
129
|
-
node(:first_child_of_first_root).
|
128
|
+
expect(node(:first_root)).to be_at_top
|
129
|
+
expect(node(:first_child_of_first_root)).to be_at_top
|
130
130
|
end
|
131
131
|
|
132
132
|
it "should return false when the node is not first in the list" do
|
133
|
-
node(:second_root).
|
134
|
-
node(:third_root).
|
135
|
-
node(:second_child_of_first_root).
|
133
|
+
expect(node(:second_root)).not_to be_at_top
|
134
|
+
expect(node(:third_root)).not_to be_at_top
|
135
|
+
expect(node(:second_child_of_first_root)).not_to be_at_top
|
136
136
|
end
|
137
137
|
end
|
138
138
|
|
139
139
|
describe '#at_bottom?' do
|
140
140
|
it "should return true when the node is last in the list" do
|
141
|
-
node(:third_root).
|
142
|
-
node(:second_child_of_first_root).
|
141
|
+
expect(node(:third_root)).to be_at_bottom
|
142
|
+
expect(node(:second_child_of_first_root)).to be_at_bottom
|
143
143
|
end
|
144
144
|
|
145
145
|
it "should return false when the node is not last in the list" do
|
146
|
-
node(:first_root).
|
147
|
-
node(:second_root).
|
148
|
-
node(:first_child_of_first_root).
|
146
|
+
expect(node(:first_root)).not_to be_at_bottom
|
147
|
+
expect(node(:second_root)).not_to be_at_bottom
|
148
|
+
expect(node(:first_child_of_first_root)).not_to be_at_bottom
|
149
149
|
end
|
150
150
|
end
|
151
151
|
|
152
152
|
describe '#last_sibling_in_list' do
|
153
153
|
it "should return the last sibling in the list containing the current sibling" do
|
154
|
-
node(:first_root).last_sibling_in_list.
|
155
|
-
node(:second_root).last_sibling_in_list.
|
156
|
-
node(:third_root).last_sibling_in_list.
|
154
|
+
expect(node(:first_root).last_sibling_in_list).to eq(node(:third_root))
|
155
|
+
expect(node(:second_root).last_sibling_in_list).to eq(node(:third_root))
|
156
|
+
expect(node(:third_root).last_sibling_in_list).to eq(node(:third_root))
|
157
157
|
end
|
158
158
|
end
|
159
159
|
|
160
160
|
describe '#first_sibling_in_list' do
|
161
161
|
it "should return the first sibling in the list containing the current sibling" do
|
162
|
-
node(:first_root).first_sibling_in_list.
|
163
|
-
node(:second_root).first_sibling_in_list.
|
164
|
-
node(:third_root).first_sibling_in_list.
|
162
|
+
expect(node(:first_root).first_sibling_in_list).to eq(node(:first_root))
|
163
|
+
expect(node(:second_root).first_sibling_in_list).to eq(node(:first_root))
|
164
|
+
expect(node(:third_root).first_sibling_in_list).to eq(node(:first_root))
|
165
165
|
end
|
166
166
|
end
|
167
167
|
|
168
|
-
describe 'ancestors' do
|
169
|
-
it "
|
168
|
+
describe '#ancestors' do
|
169
|
+
it "should be returned in the correct order" do
|
170
170
|
setup_tree <<-ENDTREE
|
171
171
|
- root:
|
172
172
|
- level_1_a
|
@@ -175,7 +175,21 @@ describe Mongoid::Tree::Ordering do
|
|
175
175
|
- leaf
|
176
176
|
ENDTREE
|
177
177
|
|
178
|
-
node(:leaf).ancestors.to_a.
|
178
|
+
expect(node(:leaf).ancestors.to_a).to eq([node(:root), node(:level_1_b), node(:level_2_a)])
|
179
|
+
end
|
180
|
+
|
181
|
+
it "should return the ancestors in correct order even after rearranging" do
|
182
|
+
setup_tree <<-ENDTREE
|
183
|
+
- root:
|
184
|
+
- child:
|
185
|
+
- subchild
|
186
|
+
ENDTREE
|
187
|
+
|
188
|
+
child = node(:child); child.parent = nil; child.save!
|
189
|
+
root = node(:root); root.parent = node(:child); root.save!
|
190
|
+
subchild = node(:subchild); subchild.parent = root; subchild.save!
|
191
|
+
|
192
|
+
expect(subchild.ancestors.to_a).to eq([child, root])
|
179
193
|
end
|
180
194
|
end
|
181
195
|
end
|
@@ -199,7 +213,7 @@ describe Mongoid::Tree::Ordering do
|
|
199
213
|
it 'should fix positions within the current list when moving an sibling away from its current parent' do
|
200
214
|
node_to_move = node(:first_child_of_first_root)
|
201
215
|
node_to_move.move_below(node(:first_child_of_second_root))
|
202
|
-
node(:second_child_of_first_root).position.
|
216
|
+
expect(node(:second_child_of_first_root).position).to eq(0)
|
203
217
|
end
|
204
218
|
|
205
219
|
it 'should work when moving to a different parent' do
|
@@ -207,8 +221,8 @@ describe Mongoid::Tree::Ordering do
|
|
207
221
|
new_parent = node(:second_root)
|
208
222
|
node_to_move.move_below(node(:first_child_of_second_root))
|
209
223
|
node_to_move.reload
|
210
|
-
node_to_move.
|
211
|
-
node(:first_child_of_second_root).
|
224
|
+
expect(node_to_move).to be_at_bottom
|
225
|
+
expect(node(:first_child_of_second_root)).to be_at_top
|
212
226
|
end
|
213
227
|
|
214
228
|
it 'should be able to move the first node below the second node' do
|
@@ -217,8 +231,8 @@ describe Mongoid::Tree::Ordering do
|
|
217
231
|
first_node.move_below(second_node)
|
218
232
|
first_node.reload
|
219
233
|
second_node.reload
|
220
|
-
second_node.
|
221
|
-
first_node.higher_siblings.to_a.
|
234
|
+
expect(second_node).to be_at_top
|
235
|
+
expect(first_node.higher_siblings.to_a).to eq([second_node])
|
222
236
|
end
|
223
237
|
|
224
238
|
it 'should be able to move the last node below the first node' do
|
@@ -227,9 +241,9 @@ describe Mongoid::Tree::Ordering do
|
|
227
241
|
last_node.move_below(first_node)
|
228
242
|
first_node.reload
|
229
243
|
last_node.reload
|
230
|
-
last_node.
|
231
|
-
node(:second_root).
|
232
|
-
last_node.higher_siblings.to_a.
|
244
|
+
expect(last_node).not_to be_at_bottom
|
245
|
+
expect(node(:second_root)).to be_at_bottom
|
246
|
+
expect(last_node.higher_siblings.to_a).to eq([first_node])
|
233
247
|
end
|
234
248
|
end
|
235
249
|
|
@@ -237,7 +251,7 @@ describe Mongoid::Tree::Ordering do
|
|
237
251
|
it 'should fix positions within the current list when moving an sibling away from its current parent' do
|
238
252
|
node_to_move = node(:first_child_of_first_root)
|
239
253
|
node_to_move.move_above(node(:first_child_of_second_root))
|
240
|
-
node(:second_child_of_first_root).position.
|
254
|
+
expect(node(:second_child_of_first_root).position).to eq(0)
|
241
255
|
end
|
242
256
|
|
243
257
|
it 'should work when moving to a different parent' do
|
@@ -245,8 +259,8 @@ describe Mongoid::Tree::Ordering do
|
|
245
259
|
new_parent = node(:second_root)
|
246
260
|
node_to_move.move_above(node(:first_child_of_second_root))
|
247
261
|
node_to_move.reload
|
248
|
-
node_to_move.
|
249
|
-
node(:first_child_of_second_root).
|
262
|
+
expect(node_to_move).to be_at_top
|
263
|
+
expect(node(:first_child_of_second_root)).to be_at_bottom
|
250
264
|
end
|
251
265
|
|
252
266
|
it 'should be able to move the last node above the second node' do
|
@@ -255,8 +269,8 @@ describe Mongoid::Tree::Ordering do
|
|
255
269
|
last_node.move_above(second_node)
|
256
270
|
last_node.reload
|
257
271
|
second_node.reload
|
258
|
-
second_node.
|
259
|
-
last_node.higher_siblings.to_a.
|
272
|
+
expect(second_node).to be_at_bottom
|
273
|
+
expect(last_node.higher_siblings.to_a).to eq([node(:first_root)])
|
260
274
|
end
|
261
275
|
|
262
276
|
it 'should be able to move the first node above the last node' do
|
@@ -265,15 +279,15 @@ describe Mongoid::Tree::Ordering do
|
|
265
279
|
first_node.move_above(last_node)
|
266
280
|
first_node.reload
|
267
281
|
last_node.reload
|
268
|
-
node(:second_root).
|
269
|
-
first_node.higher_siblings.to_a.
|
282
|
+
expect(node(:second_root)).to be_at_top
|
283
|
+
expect(first_node.higher_siblings.to_a).to eq([node(:second_root)])
|
270
284
|
end
|
271
285
|
end
|
272
286
|
|
273
287
|
describe "#move_to_top" do
|
274
288
|
it "should return true when attempting to move the first sibling" do
|
275
|
-
node(:first_root).move_to_top.
|
276
|
-
node(:first_child_of_first_root).move_to_top.
|
289
|
+
expect(node(:first_root).move_to_top).to eq(true)
|
290
|
+
expect(node(:first_child_of_first_root).move_to_top).to eq(true)
|
277
291
|
end
|
278
292
|
|
279
293
|
it "should be able to move the last sibling to the top" do
|
@@ -281,17 +295,17 @@ describe Mongoid::Tree::Ordering do
|
|
281
295
|
last_node = node(:third_root)
|
282
296
|
last_node.move_to_top
|
283
297
|
first_node.reload
|
284
|
-
last_node.
|
285
|
-
first_node.
|
286
|
-
first_node.higher_siblings.to_a.
|
287
|
-
last_node.lower_siblings.to_a.
|
298
|
+
expect(last_node).to be_at_top
|
299
|
+
expect(first_node).not_to be_at_top
|
300
|
+
expect(first_node.higher_siblings.to_a).to eq([last_node])
|
301
|
+
expect(last_node.lower_siblings.to_a).to eq([first_node, node(:second_root)])
|
288
302
|
end
|
289
303
|
end
|
290
304
|
|
291
305
|
describe "#move_to_bottom" do
|
292
306
|
it "should return true when attempting to move the last sibling" do
|
293
|
-
node(:third_root).move_to_bottom.
|
294
|
-
node(:second_child_of_first_root).move_to_bottom.
|
307
|
+
expect(node(:third_root).move_to_bottom).to eq(true)
|
308
|
+
expect(node(:second_child_of_first_root).move_to_bottom).to eq(true)
|
295
309
|
end
|
296
310
|
|
297
311
|
it "should be able to move the first sibling to the bottom" do
|
@@ -301,27 +315,27 @@ describe Mongoid::Tree::Ordering do
|
|
301
315
|
first_node.move_to_bottom
|
302
316
|
middle_node.reload
|
303
317
|
last_node.reload
|
304
|
-
first_node.
|
305
|
-
first_node.
|
306
|
-
last_node.
|
307
|
-
last_node.
|
308
|
-
middle_node.
|
309
|
-
first_node.lower_siblings.to_a.
|
310
|
-
last_node.higher_siblings.to_a.
|
318
|
+
expect(first_node).not_to be_at_top
|
319
|
+
expect(first_node).to be_at_bottom
|
320
|
+
expect(last_node).not_to be_at_bottom
|
321
|
+
expect(last_node).not_to be_at_top
|
322
|
+
expect(middle_node).to be_at_top
|
323
|
+
expect(first_node.lower_siblings.to_a).to eq([])
|
324
|
+
expect(last_node.higher_siblings.to_a).to eq([middle_node])
|
311
325
|
end
|
312
326
|
end
|
313
327
|
|
314
328
|
describe "#move_up" do
|
315
329
|
it "should correctly move nodes up" do
|
316
330
|
node(:third).move_up
|
317
|
-
node(:third_root).children.
|
331
|
+
expect(node(:third_root).children).to eq([node(:first), node(:third), node(:second)])
|
318
332
|
end
|
319
333
|
end
|
320
334
|
|
321
335
|
describe "#move_down" do
|
322
336
|
it "should correctly move nodes down" do
|
323
337
|
node(:first).move_down
|
324
|
-
node(:third_root).children.
|
338
|
+
expect(node(:third_root).children).to eq([node(:second), node(:first), node(:third)])
|
325
339
|
end
|
326
340
|
end
|
327
341
|
end # moving nodes around
|
@@ -19,7 +19,7 @@ describe Mongoid::Tree::Traversal do
|
|
19
19
|
end
|
20
20
|
|
21
21
|
it "should default to depth_first traversal" do
|
22
|
-
subject.
|
22
|
+
expect(subject).to receive(:depth_first_traversal)
|
23
23
|
subject.traverse {}
|
24
24
|
end
|
25
25
|
end
|
@@ -42,12 +42,12 @@ describe Mongoid::Tree::Traversal do
|
|
42
42
|
it "should traverse correctly" do
|
43
43
|
result = []
|
44
44
|
node(:node1).traverse(:depth_first) { |node| result << node }
|
45
|
-
result.collect { |n| n.name.to_sym }.
|
45
|
+
expect(result.collect { |n| n.name.to_sym }).to eq([:node1, :node2, :node3, :node4, :node5, :node6, :node7])
|
46
46
|
end
|
47
47
|
|
48
48
|
it "should return and array containing the results of the block for each node" do
|
49
49
|
result = node(:node1).traverse(:depth_first) { |n| n.name.to_sym }
|
50
|
-
result.
|
50
|
+
expect(result).to eq([:node1, :node2, :node3, :node4, :node5, :node6, :node7])
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
@@ -69,7 +69,7 @@ describe Mongoid::Tree::Traversal do
|
|
69
69
|
|
70
70
|
it "should traverse correctly" do
|
71
71
|
result = node(:node1).traverse(:depth_first) { |n| n.name.to_sym }
|
72
|
-
result.
|
72
|
+
expect(result).to eq([:node1, :node2, :node3, :node4, :node5, :node6, :node7])
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
@@ -92,12 +92,12 @@ describe Mongoid::Tree::Traversal do
|
|
92
92
|
it 'should iterate through the nodes in the correct order' do
|
93
93
|
result = []
|
94
94
|
node(:node1).traverse(:depth_first) { |node| result << node }
|
95
|
-
result.collect { |n| n.name.to_sym }.
|
95
|
+
expect(result.collect { |n| n.name.to_sym }).to eq([:node1, :node2, :node3, :node4, :node5, :node6, :node7])
|
96
96
|
end
|
97
97
|
|
98
98
|
it 'should return the nodes in the correct order' do
|
99
99
|
result = node(:node1).traverse(:depth_first)
|
100
|
-
result.collect { |n| n.name.to_sym }.
|
100
|
+
expect(result.collect { |n| n.name.to_sym }).to eq([:node1, :node2, :node3, :node4, :node5, :node6, :node7])
|
101
101
|
end
|
102
102
|
|
103
103
|
end
|
@@ -121,12 +121,12 @@ describe Mongoid::Tree::Traversal do
|
|
121
121
|
it "should traverse correctly" do
|
122
122
|
result = []
|
123
123
|
node(:node1).traverse(:breadth_first) { |n| result << n }
|
124
|
-
result.collect { |n| n.name.to_sym }.
|
124
|
+
expect(result.collect { |n| n.name.to_sym }).to eq([:node1, :node2, :node3, :node4, :node5, :node6, :node7])
|
125
125
|
end
|
126
126
|
|
127
127
|
it "should return and array containing the results of the block for each node" do
|
128
128
|
result = node(:node1).traverse(:breadth_first) { |n| n.name.to_sym }
|
129
|
-
result.
|
129
|
+
expect(result).to eq([:node1, :node2, :node3, :node4, :node5, :node6, :node7])
|
130
130
|
end
|
131
131
|
|
132
132
|
end
|
@@ -144,31 +144,31 @@ describe Mongoid::Tree::Traversal do
|
|
144
144
|
Node.stub(:roots).and_return [@root1, @root2]
|
145
145
|
end
|
146
146
|
|
147
|
-
it '
|
148
|
-
Node.
|
147
|
+
it 'should grab each root' do
|
148
|
+
expect(Node).to receive(:roots).and_return []
|
149
149
|
|
150
|
-
Node.traverse.
|
150
|
+
expect(Node.traverse).to eq([])
|
151
151
|
end
|
152
152
|
|
153
|
-
it '
|
154
|
-
@root1.
|
155
|
-
@root2.
|
153
|
+
it 'should default the "type" arg to :depth_first' do
|
154
|
+
expect(@root1).to receive(:traverse).with(:depth_first).and_return([])
|
155
|
+
expect(@root2).to receive(:traverse).with(:depth_first).and_return([])
|
156
156
|
|
157
|
-
Node.traverse.
|
157
|
+
expect(Node.traverse).to eq([])
|
158
158
|
end
|
159
159
|
|
160
|
-
it '
|
161
|
-
@root1.
|
162
|
-
@root2.
|
160
|
+
it 'should traverse each root' do
|
161
|
+
expect(@root1).to receive(:traverse).and_return([1, 2])
|
162
|
+
expect(@root2).to receive(:traverse).and_return([3, 4])
|
163
163
|
|
164
|
-
Node.traverse.
|
164
|
+
expect(Node.traverse).to eq([1, 2, 3, 4])
|
165
165
|
end
|
166
166
|
|
167
167
|
describe 'when the "type" arg is :breadth_first' do
|
168
168
|
|
169
|
-
it '
|
170
|
-
@root1.
|
171
|
-
@root2.
|
169
|
+
it 'should traverse breadth-first' do
|
170
|
+
expect(@root1).to receive(:traverse).with(:breadth_first).and_return([])
|
171
|
+
expect(@root2).to receive(:traverse).with(:breadth_first).and_return([])
|
172
172
|
|
173
173
|
Node.traverse :breadth_first
|
174
174
|
end
|
data/spec/mongoid/tree_spec.rb
CHANGED
@@ -6,46 +6,46 @@ describe Mongoid::Tree do
|
|
6
6
|
|
7
7
|
it "should reference many children as inverse of parent with index" do
|
8
8
|
a = Node.reflect_on_association(:children)
|
9
|
-
a.
|
10
|
-
a.macro.
|
11
|
-
a.class_name.
|
12
|
-
a.foreign_key.
|
13
|
-
Node.index_options.
|
9
|
+
expect(a).to be
|
10
|
+
expect(a.macro).to eq(:has_many)
|
11
|
+
expect(a.class_name).to eq('Node')
|
12
|
+
expect(a.foreign_key).to eq('parent_id')
|
13
|
+
expect(Node.index_options).to have_key(:parent_id => 1)
|
14
14
|
end
|
15
15
|
|
16
16
|
it "should be referenced in one parent as inverse of children" do
|
17
17
|
a = Node.reflect_on_association(:parent)
|
18
|
-
a.
|
19
|
-
a.macro.
|
20
|
-
a.class_name.
|
21
|
-
a.inverse_of.
|
18
|
+
expect(a).to be
|
19
|
+
expect(a.macro).to eq(:belongs_to)
|
20
|
+
expect(a.class_name).to eq('Node')
|
21
|
+
expect(a.inverse_of).to eq(:children)
|
22
22
|
end
|
23
23
|
|
24
24
|
it "should store parent_ids as Array with [] as default with index" do
|
25
25
|
f = Node.fields['parent_ids']
|
26
|
-
f.
|
27
|
-
f.options[:type].
|
28
|
-
f.options[:default].
|
29
|
-
Node.index_options.
|
26
|
+
expect(f).to be
|
27
|
+
expect(f.options[:type]).to eq(Array)
|
28
|
+
expect(f.options[:default]).to eq([])
|
29
|
+
expect(Node.index_options).to have_key(:parent_ids => 1)
|
30
30
|
end
|
31
31
|
|
32
32
|
describe 'when new' do
|
33
33
|
it "should not require a saved parent when adding children" do
|
34
34
|
root = Node.new(:name => 'root'); child = Node.new(:name => 'child')
|
35
|
-
expect { root.children << child; root.save! }.to_not raise_error
|
36
|
-
child.
|
35
|
+
expect { root.children << child; root.save! }.to_not raise_error
|
36
|
+
expect(child).to be_persisted
|
37
37
|
end
|
38
38
|
|
39
39
|
it "should not be saved when parent is not saved" do
|
40
40
|
root = Node.new(:name => 'root'); child = Node.new(:name => 'child')
|
41
|
-
child.
|
41
|
+
expect(child).not_to receive(:save)
|
42
42
|
root.children << child
|
43
43
|
end
|
44
44
|
|
45
45
|
it "should save its unsaved children" do
|
46
46
|
root = Node.new(:name => 'root'); child = Node.new(:name => 'child')
|
47
47
|
root.children << child
|
48
|
-
child.
|
48
|
+
expect(child).to receive(:save)
|
49
49
|
root.save
|
50
50
|
end
|
51
51
|
end
|
@@ -66,61 +66,61 @@ describe Mongoid::Tree do
|
|
66
66
|
it "should set the child's parent_id when added to parent's children" do
|
67
67
|
root = Node.create; child = Node.create
|
68
68
|
root.children << child
|
69
|
-
child.parent.
|
70
|
-
child.parent_id.
|
69
|
+
expect(child.parent).to eq(root)
|
70
|
+
expect(child.parent_id).to eq(root.id)
|
71
71
|
end
|
72
72
|
|
73
73
|
it "should set the child's parent_id parent is set on child" do
|
74
74
|
root = Node.create; child = Node.create
|
75
75
|
child.parent = root
|
76
|
-
child.parent.
|
77
|
-
child.parent_id.
|
76
|
+
expect(child.parent).to eq(root)
|
77
|
+
expect(child.parent_id).to eq(root.id)
|
78
78
|
end
|
79
79
|
|
80
80
|
it "should rebuild its parent_ids" do
|
81
81
|
root = Node.create; child = Node.create
|
82
82
|
root.children << child
|
83
|
-
child.parent_ids.
|
83
|
+
expect(child.parent_ids).to eq([root.id])
|
84
84
|
end
|
85
85
|
|
86
86
|
it "should rebuild its children's parent_ids when its own parent_ids changed" do
|
87
87
|
other_root = node(:other_root); child = node(:child); subchild = node(:subchild);
|
88
88
|
other_root.children << child
|
89
89
|
subchild.reload # To get the updated version
|
90
|
-
subchild.parent_ids.
|
90
|
+
expect(subchild.parent_ids).to eq([other_root.id, child.id])
|
91
91
|
end
|
92
92
|
|
93
93
|
it "should correctly rebuild its descendants' parent_ids when moved into an other subtree" do
|
94
94
|
subchild = node(:subchild); subsubchild = node(:subsubchild); other_child = node(:other_child)
|
95
95
|
other_child.children << subchild
|
96
96
|
subsubchild.reload
|
97
|
-
subsubchild.parent_ids.
|
97
|
+
expect(subsubchild.parent_ids).to eq([node(:other_root).id, other_child.id, subchild.id])
|
98
98
|
end
|
99
99
|
|
100
100
|
it "should rebuild its children's parent_ids when its own parent_id is removed" do
|
101
101
|
c = node(:child)
|
102
102
|
c.parent_id = nil
|
103
103
|
c.save
|
104
|
-
node(:subchild).parent_ids.
|
104
|
+
expect(node(:subchild).parent_ids).to eq([node(:child).id])
|
105
105
|
end
|
106
106
|
|
107
107
|
it "should not rebuild its children's parent_ids when it's not required" do
|
108
108
|
root = node(:root)
|
109
|
-
root.
|
109
|
+
expect(root).not_to receive(:rearrange_children)
|
110
110
|
root.save
|
111
111
|
end
|
112
112
|
|
113
113
|
it "should prevent cycles" do
|
114
114
|
child = node(:child)
|
115
115
|
child.parent = node(:subchild)
|
116
|
-
child.
|
117
|
-
child.errors[:parent_id].
|
116
|
+
expect(child).not_to be_valid
|
117
|
+
expect(child.errors[:parent_id]).not_to be_nil
|
118
118
|
end
|
119
119
|
|
120
120
|
it "should save its children when added" do
|
121
121
|
new_child = Node.new(:name => 'new_child')
|
122
122
|
node(:root).children << new_child
|
123
|
-
new_child.
|
123
|
+
expect(new_child).to be_persisted
|
124
124
|
end
|
125
125
|
end
|
126
126
|
|
@@ -139,7 +139,7 @@ describe Mongoid::Tree do
|
|
139
139
|
it "should allow to store any subclass within the tree" do
|
140
140
|
subclassed = SubclassedNode.create!(:name => 'subclassed_subchild')
|
141
141
|
node(:child).children << subclassed
|
142
|
-
subclassed.root.
|
142
|
+
expect(subclassed.root).to eq(node(:root))
|
143
143
|
end
|
144
144
|
|
145
145
|
end
|
@@ -159,23 +159,23 @@ describe Mongoid::Tree do
|
|
159
159
|
describe ':nullify_children' do
|
160
160
|
it "should set its children's parent_id to null" do
|
161
161
|
node(:root).nullify_children
|
162
|
-
node(:child).
|
163
|
-
node(:subchild).reload.
|
162
|
+
expect(node(:child)).to be_root
|
163
|
+
expect(node(:subchild).reload).not_to be_descendant_of node(:root)
|
164
164
|
end
|
165
165
|
end
|
166
166
|
|
167
167
|
describe ':move_children_to_parent' do
|
168
168
|
it "should set its childen's parent_id to the documents parent_id" do
|
169
169
|
node(:child).move_children_to_parent
|
170
|
-
node(:child).
|
171
|
-
node(:root).children.to_a.
|
170
|
+
expect(node(:child)).to be_leaf
|
171
|
+
expect(node(:root).children.to_a).to match_array([node(:child), node(:other_child), node(:subchild)])
|
172
172
|
end
|
173
173
|
end
|
174
174
|
|
175
175
|
describe ':destroy_children' do
|
176
176
|
it "should destroy all children" do
|
177
177
|
root = node(:root)
|
178
|
-
root.children.
|
178
|
+
expect(root.children).to receive(:destroy_all)
|
179
179
|
root.destroy_children
|
180
180
|
end
|
181
181
|
end
|
@@ -183,7 +183,7 @@ describe Mongoid::Tree do
|
|
183
183
|
describe ':delete_descendants' do
|
184
184
|
it "should delete all descendants" do
|
185
185
|
root = node(:root)
|
186
|
-
Node.
|
186
|
+
expect(Node).to receive(:delete_all).with(:conditions => { :parent_ids => root.id })
|
187
187
|
root.delete_descendants
|
188
188
|
end
|
189
189
|
end
|
@@ -204,137 +204,163 @@ describe Mongoid::Tree do
|
|
204
204
|
|
205
205
|
describe '.root' do
|
206
206
|
it "should return the first root document" do
|
207
|
-
Node.root.
|
207
|
+
expect(Node.root).to eq(node(:root))
|
208
208
|
end
|
209
209
|
end
|
210
210
|
|
211
211
|
describe '.roots' do
|
212
212
|
it "should return all root documents" do
|
213
|
-
Node.roots.to_a.
|
213
|
+
expect(Node.roots.to_a).to eq([node(:root), node(:other_root)])
|
214
214
|
end
|
215
215
|
end
|
216
216
|
|
217
217
|
describe '.leaves' do
|
218
218
|
it "should return all leaf documents" do
|
219
|
-
Node.leaves.to_a.
|
219
|
+
expect(Node.leaves.to_a).to match_array([node(:subchild), node(:other_child), node(:other_root)])
|
220
220
|
end
|
221
221
|
end
|
222
222
|
|
223
223
|
describe '#root?' do
|
224
224
|
it "should return true for root documents" do
|
225
|
-
node(:root).
|
225
|
+
expect(node(:root)).to be_root
|
226
226
|
end
|
227
227
|
|
228
228
|
it "should return false for non-root documents" do
|
229
|
-
node(:child).
|
229
|
+
expect(node(:child)).not_to be_root
|
230
230
|
end
|
231
231
|
end
|
232
232
|
|
233
233
|
describe '#leaf?' do
|
234
234
|
it "should return true for leaf documents" do
|
235
|
-
node(:subchild).
|
236
|
-
node(:other_child).
|
237
|
-
Node.new.
|
235
|
+
expect(node(:subchild)).to be_leaf
|
236
|
+
expect(node(:other_child)).to be_leaf
|
237
|
+
expect(Node.new).to be_leaf
|
238
238
|
end
|
239
239
|
|
240
240
|
it "should return false for non-leaf documents" do
|
241
|
-
node(:child).
|
242
|
-
node(:root).
|
241
|
+
expect(node(:child)).not_to be_leaf
|
242
|
+
expect(node(:root)).not_to be_leaf
|
243
243
|
end
|
244
244
|
end
|
245
245
|
|
246
246
|
describe '#depth' do
|
247
247
|
it "should return the depth of this document" do
|
248
|
-
node(:root).depth.
|
249
|
-
node(:child).depth.
|
250
|
-
node(:subchild).depth.
|
248
|
+
expect(node(:root).depth).to eq(0)
|
249
|
+
expect(node(:child).depth).to eq(1)
|
250
|
+
expect(node(:subchild).depth).to eq(2)
|
251
251
|
end
|
252
252
|
end
|
253
253
|
|
254
254
|
describe '#root' do
|
255
255
|
it "should return the root for this document" do
|
256
|
-
node(:subchild).root.
|
256
|
+
expect(node(:subchild).root).to eq(node(:root))
|
257
257
|
end
|
258
258
|
|
259
259
|
it "should return itself when there is no root" do
|
260
260
|
new_node = Node.new
|
261
|
-
new_node.root.
|
261
|
+
expect(new_node.root).to be(new_node)
|
262
262
|
end
|
263
263
|
|
264
264
|
it "should return it root when it's not saved yet" do
|
265
265
|
root = Node.new(:name => 'root')
|
266
266
|
new_node = Node.new(:name => 'child')
|
267
267
|
new_node.parent = root
|
268
|
-
new_node.root.
|
268
|
+
expect(new_node.root).to be(root)
|
269
269
|
end
|
270
270
|
end
|
271
271
|
|
272
272
|
describe 'ancestors' do
|
273
|
-
|
274
|
-
|
273
|
+
describe '#ancestors' do
|
274
|
+
it "should return the documents ancestors" do
|
275
|
+
expect(node(:subchild).ancestors.to_a).to eq([node(:root), node(:child)])
|
276
|
+
end
|
277
|
+
|
278
|
+
it "should return the ancestors in correct order even after rearranging" do
|
279
|
+
setup_tree <<-ENDTREE
|
280
|
+
- root:
|
281
|
+
- child:
|
282
|
+
- subchild
|
283
|
+
ENDTREE
|
284
|
+
|
285
|
+
child = node(:child); child.parent = nil; child.save!
|
286
|
+
root = node(:root); root.parent = node(:child); root.save!
|
287
|
+
subchild = node(:subchild); subchild.parent = root; subchild.save!
|
288
|
+
|
289
|
+
expect(subchild.ancestors.to_a).to eq([child, root])
|
290
|
+
end
|
275
291
|
end
|
276
292
|
|
277
|
-
|
278
|
-
|
293
|
+
describe '#ancestors_and_self' do
|
294
|
+
it "should return the documents ancestors and itself" do
|
295
|
+
expect(node(:subchild).ancestors_and_self.to_a).to eq([node(:root), node(:child), node(:subchild)])
|
296
|
+
end
|
279
297
|
end
|
280
298
|
|
281
299
|
describe '#ancestor_of?' do
|
282
300
|
it "should return true for ancestors" do
|
283
|
-
node(:child).
|
301
|
+
expect(node(:child)).to be_ancestor_of(node(:subchild))
|
284
302
|
end
|
285
303
|
|
286
304
|
it "should return false for non-ancestors" do
|
287
|
-
node(:other_child).
|
305
|
+
expect(node(:other_child)).not_to be_ancestor_of(node(:subchild))
|
288
306
|
end
|
289
307
|
end
|
290
308
|
end
|
291
309
|
|
292
310
|
describe 'descendants' do
|
293
|
-
|
294
|
-
|
311
|
+
describe '#descendants' do
|
312
|
+
it "should return the documents descendants" do
|
313
|
+
expect(node(:root).descendants.to_a).to match_array([node(:child), node(:other_child), node(:subchild)])
|
314
|
+
end
|
295
315
|
end
|
296
316
|
|
297
|
-
|
298
|
-
|
317
|
+
describe '#descendants_and_self' do
|
318
|
+
it "should return the documents descendants and itself" do
|
319
|
+
expect(node(:root).descendants_and_self.to_a).to match_array([node(:root), node(:child), node(:other_child), node(:subchild)])
|
320
|
+
end
|
299
321
|
end
|
300
322
|
|
301
323
|
describe '#descendant_of?' do
|
302
324
|
it "should return true for descendants" do
|
303
325
|
subchild = node(:subchild)
|
304
|
-
subchild.
|
305
|
-
subchild.
|
326
|
+
expect(subchild).to be_descendant_of(node(:child))
|
327
|
+
expect(subchild).to be_descendant_of(node(:root))
|
306
328
|
end
|
307
329
|
|
308
330
|
it "should return false for non-descendants" do
|
309
|
-
node(:subchild).
|
331
|
+
expect(node(:subchild)).not_to be_descendant_of(node(:other_child))
|
310
332
|
end
|
311
333
|
end
|
312
334
|
end
|
313
335
|
|
314
336
|
describe 'siblings' do
|
315
|
-
|
316
|
-
|
337
|
+
describe '#siblings' do
|
338
|
+
it "should return the documents siblings" do
|
339
|
+
expect(node(:child).siblings.to_a).to eq([node(:other_child)])
|
340
|
+
end
|
317
341
|
end
|
318
342
|
|
319
|
-
|
320
|
-
|
321
|
-
|
343
|
+
describe '#siblings_and_self' do
|
344
|
+
it "should return the documents siblings and itself" do
|
345
|
+
expect(node(:child).siblings_and_self).to be_kind_of(Mongoid::Criteria)
|
346
|
+
expect(node(:child).siblings_and_self.to_a).to eq([node(:child), node(:other_child)])
|
347
|
+
end
|
322
348
|
end
|
323
349
|
|
324
350
|
describe '#sibling_of?' do
|
325
351
|
it "should return true for siblings" do
|
326
|
-
node(:child).
|
352
|
+
expect(node(:child)).to be_sibling_of(node(:other_child))
|
327
353
|
end
|
328
354
|
|
329
355
|
it "should return false for non-siblings" do
|
330
|
-
node(:root).
|
356
|
+
expect(node(:root)).not_to be_sibling_of(node(:other_child))
|
331
357
|
end
|
332
358
|
end
|
333
359
|
end
|
334
360
|
|
335
361
|
describe '#leaves' do
|
336
362
|
it "should return this documents leaves" do
|
337
|
-
node(:root).leaves.to_a.
|
363
|
+
expect(node(:root).leaves.to_a).to match_array([node(:other_child), node(:subchild)])
|
338
364
|
end
|
339
365
|
end
|
340
366
|
|
@@ -347,11 +373,11 @@ describe Mongoid::Tree do
|
|
347
373
|
end
|
348
374
|
|
349
375
|
it "should provide a before_rearrange callback" do
|
350
|
-
Node.
|
376
|
+
expect(Node).to respond_to :before_rearrange
|
351
377
|
end
|
352
378
|
|
353
379
|
it "should provida an after_rearrange callback" do
|
354
|
-
Node.
|
380
|
+
expect(Node).to respond_to :after_rearrange
|
355
381
|
end
|
356
382
|
|
357
383
|
describe 'before rearrange callback' do
|
@@ -359,8 +385,8 @@ describe Mongoid::Tree do
|
|
359
385
|
it "should be called before the document is rearranged" do
|
360
386
|
Node.before_rearrange :callback
|
361
387
|
node = Node.new
|
362
|
-
node.
|
363
|
-
node.
|
388
|
+
expect(node).to receive(:callback).ordered
|
389
|
+
expect(node).to receive(:rearrange).ordered
|
364
390
|
node.save
|
365
391
|
end
|
366
392
|
|
@@ -371,8 +397,8 @@ describe Mongoid::Tree do
|
|
371
397
|
it "should be called after the document is rearranged" do
|
372
398
|
Node.after_rearrange :callback
|
373
399
|
node = Node.new
|
374
|
-
node.
|
375
|
-
node.
|
400
|
+
expect(node).to receive(:rearrange).ordered
|
401
|
+
expect(node).to receive(:callback).ordered
|
376
402
|
node.save
|
377
403
|
end
|
378
404
|
|
@@ -383,7 +409,7 @@ describe Mongoid::Tree do
|
|
383
409
|
it 'should not raise a NoMethodError' do
|
384
410
|
node = NodeWithEmbeddedDocument.new
|
385
411
|
document = node.build_embedded_document
|
386
|
-
expect { node.save }.to_not raise_error
|
412
|
+
expect { node.save }.to_not raise_error
|
387
413
|
end
|
388
414
|
|
389
415
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,74 +1,66 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongoid-tree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
5
|
-
prerelease:
|
4
|
+
version: 1.0.2
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Benedikt Deicke
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2013-07-14 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: mongoid
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
17
|
- - <=
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '4.0'
|
22
|
-
- -
|
20
|
+
- - '>='
|
23
21
|
- !ruby/object:Gem::Version
|
24
22
|
version: '3.0'
|
25
23
|
type: :runtime
|
26
24
|
prerelease: false
|
27
25
|
version_requirements: !ruby/object:Gem::Requirement
|
28
|
-
none: false
|
29
26
|
requirements:
|
30
27
|
- - <=
|
31
28
|
- !ruby/object:Gem::Version
|
32
29
|
version: '4.0'
|
33
|
-
- -
|
30
|
+
- - '>='
|
34
31
|
- !ruby/object:Gem::Version
|
35
32
|
version: '3.0'
|
36
33
|
- !ruby/object:Gem::Dependency
|
37
34
|
name: rake
|
38
35
|
requirement: !ruby/object:Gem::Requirement
|
39
|
-
none: false
|
40
36
|
requirements:
|
41
|
-
- -
|
37
|
+
- - '>='
|
42
38
|
- !ruby/object:Gem::Version
|
43
39
|
version: 0.9.2
|
44
40
|
type: :development
|
45
41
|
prerelease: false
|
46
42
|
version_requirements: !ruby/object:Gem::Requirement
|
47
|
-
none: false
|
48
43
|
requirements:
|
49
|
-
- -
|
44
|
+
- - '>='
|
50
45
|
- !ruby/object:Gem::Version
|
51
46
|
version: 0.9.2
|
52
47
|
- !ruby/object:Gem::Dependency
|
53
48
|
name: rspec
|
54
49
|
requirement: !ruby/object:Gem::Requirement
|
55
|
-
none: false
|
56
50
|
requirements:
|
57
51
|
- - ~>
|
58
52
|
- !ruby/object:Gem::Version
|
59
|
-
version: '2.
|
53
|
+
version: '2.14'
|
60
54
|
type: :development
|
61
55
|
prerelease: false
|
62
56
|
version_requirements: !ruby/object:Gem::Requirement
|
63
|
-
none: false
|
64
57
|
requirements:
|
65
58
|
- - ~>
|
66
59
|
- !ruby/object:Gem::Version
|
67
|
-
version: '2.
|
60
|
+
version: '2.14'
|
68
61
|
- !ruby/object:Gem::Dependency
|
69
62
|
name: yard
|
70
63
|
requirement: !ruby/object:Gem::Requirement
|
71
|
-
none: false
|
72
64
|
requirements:
|
73
65
|
- - ~>
|
74
66
|
- !ruby/object:Gem::Version
|
@@ -76,7 +68,6 @@ dependencies:
|
|
76
68
|
type: :development
|
77
69
|
prerelease: false
|
78
70
|
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
none: false
|
80
71
|
requirements:
|
81
72
|
- - ~>
|
82
73
|
- !ruby/object:Gem::Version
|
@@ -104,27 +95,26 @@ files:
|
|
104
95
|
- .rspec
|
105
96
|
homepage: https://github.com/benedikt/mongoid-tree
|
106
97
|
licenses: []
|
98
|
+
metadata: {}
|
107
99
|
post_install_message:
|
108
100
|
rdoc_options: []
|
109
101
|
require_paths:
|
110
102
|
- lib
|
111
103
|
required_ruby_version: !ruby/object:Gem::Requirement
|
112
|
-
none: false
|
113
104
|
requirements:
|
114
|
-
- -
|
105
|
+
- - '>='
|
115
106
|
- !ruby/object:Gem::Version
|
116
107
|
version: '0'
|
117
108
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
|
-
none: false
|
119
109
|
requirements:
|
120
|
-
- -
|
110
|
+
- - '>='
|
121
111
|
- !ruby/object:Gem::Version
|
122
112
|
version: '0'
|
123
113
|
requirements: []
|
124
114
|
rubyforge_project:
|
125
|
-
rubygems_version:
|
115
|
+
rubygems_version: 2.0.0
|
126
116
|
signing_key:
|
127
|
-
specification_version:
|
117
|
+
specification_version: 4
|
128
118
|
summary: A tree structure for Mongoid documents
|
129
119
|
test_files: []
|
130
120
|
has_rdoc:
|