mongoid-tree 0.5.0 → 0.6.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/Gemfile +1 -1
- data/README.rdoc +16 -2
- data/Rakefile +2 -1
- data/lib/mongoid/tree.rb +15 -19
- data/lib/mongoid/tree/ordering.rb +4 -16
- data/spec/mongoid/tree/ordering_spec.rb +1 -1
- data/spec/mongoid/tree_spec.rb +37 -7
- data/spec/support/models/node.rb +14 -2
- metadata +31 -46
data/Gemfile
CHANGED
data/README.rdoc
CHANGED
@@ -5,7 +5,7 @@ A tree structure for Mongoid documents using the materialized path pattern
|
|
5
5
|
|
6
6
|
== Requirements
|
7
7
|
|
8
|
-
* mongoid (
|
8
|
+
* mongoid (~> 2.0.0)
|
9
9
|
|
10
10
|
|
11
11
|
== Install
|
@@ -154,6 +154,20 @@ Example:
|
|
154
154
|
end
|
155
155
|
|
156
156
|
|
157
|
+
=== Validations
|
158
|
+
|
159
|
+
Mongoid::Tree currently does not validate the document's children or parent associations by default. To explicitly enable validation for children and parent documents it's required to add a <tt>validates_associated</tt> validation.
|
160
|
+
|
161
|
+
Example
|
162
|
+
|
163
|
+
class Node
|
164
|
+
include Mongoid::Document
|
165
|
+
include Mongoid::Tree
|
166
|
+
|
167
|
+
validates_associated :parent, :children
|
168
|
+
end
|
169
|
+
|
170
|
+
|
157
171
|
== Known issues
|
158
172
|
|
159
173
|
See https://github.com/benedikt/mongoid-tree/issues
|
@@ -171,4 +185,4 @@ See a list of all contributors at https://github.com/benedikt/mongoid-tree/contr
|
|
171
185
|
|
172
186
|
== Copyright
|
173
187
|
|
174
|
-
Copyright (c) 2010 Benedikt Deicke. See LICENSE for details.
|
188
|
+
Copyright (c) 2010-2011 Benedikt Deicke. See LICENSE for details.
|
data/Rakefile
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'rspec/core/rake_task'
|
2
|
-
require '
|
2
|
+
require 'rdoc/task'
|
3
3
|
|
4
4
|
spec = Gem::Specification.load("mongoid-tree.gemspec")
|
5
5
|
|
@@ -8,6 +8,7 @@ RSpec::Core::RakeTask.new(:spec)
|
|
8
8
|
task :default => :spec
|
9
9
|
|
10
10
|
Rake::RDocTask.new do |rdoc|
|
11
|
+
rdoc.generator = 'hanna'
|
11
12
|
rdoc.rdoc_dir = 'doc'
|
12
13
|
rdoc.title = "#{spec.name} #{spec.version}"
|
13
14
|
rdoc.options += spec.rdoc_options
|
data/lib/mongoid/tree.rb
CHANGED
@@ -83,17 +83,9 @@ module Mongoid # :nodoc:
|
|
83
83
|
autoload :Traversal, 'mongoid/tree/traversal'
|
84
84
|
|
85
85
|
included do
|
86
|
-
references_many :children, :class_name => self.name, :foreign_key => :parent_id, :inverse_of => :parent
|
87
|
-
def <<(*objects) # :nodoc:
|
88
|
-
super
|
89
|
-
objects.each do |c|
|
90
|
-
c.parent = @parent
|
91
|
-
c.save
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
86
|
+
references_many :children, :class_name => self.name, :foreign_key => :parent_id, :inverse_of => :parent, :autosave => true, :validate => false
|
95
87
|
|
96
|
-
referenced_in :parent, :class_name => self.name, :inverse_of => :children, :index => true
|
88
|
+
referenced_in :parent, :class_name => self.name, :inverse_of => :children, :index => true, :validate => false
|
97
89
|
|
98
90
|
field :parent_ids, :type => Array, :default => []
|
99
91
|
index :parent_ids
|
@@ -194,17 +186,21 @@ module Mongoid # :nodoc:
|
|
194
186
|
##
|
195
187
|
# Returns this document's root node
|
196
188
|
def root
|
197
|
-
|
189
|
+
if parent_ids.present?
|
190
|
+
return base_class.find(parent_ids.first)
|
191
|
+
else
|
192
|
+
return self.root? ? self : self.parent.root
|
193
|
+
end
|
198
194
|
end
|
199
195
|
|
200
196
|
##
|
201
|
-
# Returns this document's ancestors
|
197
|
+
# Returns a chainable criteria for this document's ancestors
|
202
198
|
def ancestors
|
203
199
|
base_class.where(:_id.in => parent_ids)
|
204
200
|
end
|
205
201
|
|
206
202
|
##
|
207
|
-
# Returns this document's ancestors and itself
|
203
|
+
# Returns an array of this document's ancestors and itself
|
208
204
|
def ancestors_and_self
|
209
205
|
ancestors + [self]
|
210
206
|
end
|
@@ -216,13 +212,13 @@ module Mongoid # :nodoc:
|
|
216
212
|
end
|
217
213
|
|
218
214
|
##
|
219
|
-
# Returns this document's descendants
|
215
|
+
# Returns a chainable criteria for this document's descendants
|
220
216
|
def descendants
|
221
217
|
base_class.where(:parent_ids => self.id)
|
222
218
|
end
|
223
219
|
|
224
220
|
##
|
225
|
-
# Returns this document's descendants and itself
|
221
|
+
# Returns and array of this document's descendants and itself
|
226
222
|
def descendants_and_self
|
227
223
|
[self] + descendants
|
228
224
|
end
|
@@ -272,7 +268,7 @@ module Mongoid # :nodoc:
|
|
272
268
|
##
|
273
269
|
# Nullifies all children's parent_id
|
274
270
|
def nullify_children
|
275
|
-
children.
|
271
|
+
children.nullify_all
|
276
272
|
end
|
277
273
|
|
278
274
|
##
|
@@ -309,11 +305,11 @@ module Mongoid # :nodoc:
|
|
309
305
|
|
310
306
|
def rearrange_children
|
311
307
|
@rearrange_children = false
|
312
|
-
self.children.
|
308
|
+
self.children.each { |c| c.save }
|
313
309
|
end
|
314
310
|
|
315
311
|
def position_in_tree
|
316
312
|
errors.add(:parent_id, :invalid) if self.parent_ids.include?(self.id)
|
317
313
|
end
|
318
|
-
end
|
319
|
-
end
|
314
|
+
end
|
315
|
+
end
|
@@ -33,27 +33,15 @@ module Mongoid
|
|
33
33
|
extend ActiveSupport::Concern
|
34
34
|
|
35
35
|
included do
|
36
|
-
reflect_on_association(:children).options[:default_order] = :position.asc
|
37
|
-
|
38
36
|
field :position, :type => Integer
|
39
37
|
|
38
|
+
default_scope asc(:position)
|
39
|
+
|
40
40
|
before_save :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
|
44
44
|
|
45
|
-
##
|
46
|
-
# :singleton-method: roots
|
47
|
-
# Returns all root documents ordered by position
|
48
|
-
|
49
|
-
module ClassMethods # :nodoc:
|
50
|
-
|
51
|
-
def roots
|
52
|
-
super.order_by(:position.asc)
|
53
|
-
end
|
54
|
-
|
55
|
-
end
|
56
|
-
|
57
45
|
##
|
58
46
|
# Returns siblings below the current document.
|
59
47
|
# Siblings with a position greater than this documents's position.
|
@@ -71,13 +59,13 @@ module Mongoid
|
|
71
59
|
##
|
72
60
|
# Returns the lowest sibling (could be self)
|
73
61
|
def last_sibling_in_list
|
74
|
-
siblings_and_self.
|
62
|
+
siblings_and_self.last
|
75
63
|
end
|
76
64
|
|
77
65
|
##
|
78
66
|
# Returns the highest sibling (could be self)
|
79
67
|
def first_sibling_in_list
|
80
|
-
siblings_and_self.
|
68
|
+
siblings_and_self.first
|
81
69
|
end
|
82
70
|
|
83
71
|
##
|
data/spec/mongoid/tree_spec.rb
CHANGED
@@ -7,19 +7,18 @@ describe Mongoid::Tree do
|
|
7
7
|
it "should reference many children as inverse of parent with index" do
|
8
8
|
a = Node.reflect_on_association(:children)
|
9
9
|
a.should be
|
10
|
-
a.
|
11
|
-
a.
|
12
|
-
a.
|
10
|
+
a.macro.should eql(:references_many)
|
11
|
+
a.class_name.should eql('Node')
|
12
|
+
a.foreign_key.should eql('parent_id')
|
13
13
|
Node.index_options.should have_key('parent_id')
|
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
18
|
a.should be
|
19
|
-
a.
|
20
|
-
a.
|
21
|
-
a.
|
22
|
-
a.options.index.should be_true
|
19
|
+
a.macro.should eql(:referenced_in)
|
20
|
+
a.class_name.should eql('Node')
|
21
|
+
a.inverse_of.should eql(:children)
|
23
22
|
end
|
24
23
|
|
25
24
|
it "should store parent_ids as Array with [] as default with index" do
|
@@ -36,6 +35,19 @@ describe Mongoid::Tree do
|
|
36
35
|
expect { root.children << child; root.save! }.to_not raise_error(Mongoid::Errors::DocumentNotFound)
|
37
36
|
child.should be_persisted
|
38
37
|
end
|
38
|
+
|
39
|
+
it "should not be saved when parent is not saved" do
|
40
|
+
root = Node.new(:name => 'root'); child = Node.new(:name => 'child')
|
41
|
+
child.should_not_receive(:save)
|
42
|
+
root.children << child
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should save its unsaved children" do
|
46
|
+
root = Node.new(:name => 'root'); child = Node.new(:name => 'child')
|
47
|
+
root.children << child
|
48
|
+
child.should_receive(:save)
|
49
|
+
root.save
|
50
|
+
end
|
39
51
|
end
|
40
52
|
|
41
53
|
describe 'when saved' do
|
@@ -104,6 +116,12 @@ describe Mongoid::Tree do
|
|
104
116
|
child.should_not be_valid
|
105
117
|
child.errors[:parent_id].should_not be_nil
|
106
118
|
end
|
119
|
+
|
120
|
+
it "should save its children when added" do
|
121
|
+
new_child = Node.new(:name => 'new_child')
|
122
|
+
node(:root).children << new_child
|
123
|
+
new_child.should be_persisted
|
124
|
+
end
|
107
125
|
end
|
108
126
|
|
109
127
|
describe 'when subclassed' do
|
@@ -237,6 +255,18 @@ describe Mongoid::Tree do
|
|
237
255
|
it "should return the root for this document" do
|
238
256
|
node(:subchild).root.should == node(:root)
|
239
257
|
end
|
258
|
+
|
259
|
+
it "should return itself when there is no root" do
|
260
|
+
new_node = Node.new
|
261
|
+
new_node.root.should be(new_node)
|
262
|
+
end
|
263
|
+
|
264
|
+
it "should return it root when it's not saved yet" do
|
265
|
+
root = Node.new(:name => 'root')
|
266
|
+
new_node = Node.new(:name => 'child')
|
267
|
+
new_node.parent = root
|
268
|
+
new_node.root.should be(root)
|
269
|
+
end
|
240
270
|
end
|
241
271
|
|
242
272
|
describe 'ancestors' do
|
data/spec/support/models/node.rb
CHANGED
@@ -11,6 +11,18 @@ end
|
|
11
11
|
class SubclassedNode < Node
|
12
12
|
end
|
13
13
|
|
14
|
-
|
14
|
+
# Adding ordering on subclasses currently doesn't work as expected.
|
15
|
+
#
|
16
|
+
# class OrderedNode < Node
|
17
|
+
# include Mongoid::Tree::Ordering
|
18
|
+
# end
|
19
|
+
class OrderedNode
|
20
|
+
include Mongoid::Document
|
21
|
+
include Mongoid::Tree
|
22
|
+
include Mongoid::Tree::Traversal
|
15
23
|
include Mongoid::Tree::Ordering
|
16
|
-
|
24
|
+
|
25
|
+
field :name
|
26
|
+
|
27
|
+
attr_accessible :name
|
28
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongoid-tree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 5
|
9
|
-
- 0
|
10
|
-
version: 0.5.0
|
4
|
+
prerelease:
|
5
|
+
version: 0.6.0
|
11
6
|
platform: ruby
|
12
7
|
authors:
|
13
8
|
- Benedikt Deicke
|
@@ -15,74 +10,64 @@ autorequire:
|
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
12
|
|
18
|
-
date:
|
13
|
+
date: 2011-03-30 00:00:00 +02:00
|
19
14
|
default_executable:
|
20
15
|
dependencies:
|
21
16
|
- !ruby/object:Gem::Dependency
|
22
17
|
name: mongoid
|
23
|
-
prerelease: false
|
24
18
|
requirement: &id001 !ruby/object:Gem::Requirement
|
25
19
|
none: false
|
26
20
|
requirements:
|
27
|
-
- -
|
21
|
+
- - ~>
|
28
22
|
- !ruby/object:Gem::Version
|
29
|
-
|
30
|
-
segments:
|
31
|
-
- 2
|
32
|
-
- 0
|
33
|
-
- 0
|
34
|
-
- beta
|
35
|
-
- 20
|
36
|
-
version: 2.0.0.beta.20
|
23
|
+
version: 2.0.0
|
37
24
|
type: :runtime
|
25
|
+
prerelease: false
|
38
26
|
version_requirements: *id001
|
39
27
|
- !ruby/object:Gem::Dependency
|
40
|
-
name:
|
41
|
-
prerelease: false
|
28
|
+
name: rake
|
42
29
|
requirement: &id002 !ruby/object:Gem::Requirement
|
43
30
|
none: false
|
44
31
|
requirements:
|
45
|
-
- -
|
32
|
+
- - ">="
|
46
33
|
- !ruby/object:Gem::Version
|
47
|
-
|
48
|
-
segments:
|
49
|
-
- 2
|
50
|
-
- 3
|
51
|
-
version: "2.3"
|
34
|
+
version: 0.8.7
|
52
35
|
type: :development
|
36
|
+
prerelease: false
|
53
37
|
version_requirements: *id002
|
54
38
|
- !ruby/object:Gem::Dependency
|
55
|
-
name:
|
56
|
-
prerelease: false
|
39
|
+
name: rspec
|
57
40
|
requirement: &id003 !ruby/object:Gem::Requirement
|
58
41
|
none: false
|
59
42
|
requirements:
|
60
|
-
- -
|
43
|
+
- - ~>
|
61
44
|
- !ruby/object:Gem::Version
|
62
|
-
|
63
|
-
segments:
|
64
|
-
- 4
|
65
|
-
- 3
|
66
|
-
- 2
|
67
|
-
version: 4.3.2
|
45
|
+
version: "2.3"
|
68
46
|
type: :development
|
47
|
+
prerelease: false
|
69
48
|
version_requirements: *id003
|
70
49
|
- !ruby/object:Gem::Dependency
|
71
|
-
name:
|
72
|
-
prerelease: false
|
50
|
+
name: autotest
|
73
51
|
requirement: &id004 !ruby/object:Gem::Requirement
|
74
52
|
none: false
|
75
53
|
requirements:
|
76
54
|
- - ">="
|
77
55
|
- !ruby/object:Gem::Version
|
78
|
-
|
79
|
-
segments:
|
80
|
-
- 0
|
81
|
-
- 1
|
82
|
-
- 12
|
83
|
-
version: 0.1.12
|
56
|
+
version: 4.3.2
|
84
57
|
type: :development
|
58
|
+
prerelease: false
|
85
59
|
version_requirements: *id004
|
60
|
+
- !ruby/object:Gem::Dependency
|
61
|
+
name: hanna-nouveau
|
62
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 0.2.2
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: *id005
|
86
71
|
description: A tree structure for Mongoid documents using the materialized path pattern
|
87
72
|
email:
|
88
73
|
- benedikt@synatic.net
|
@@ -124,7 +109,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
124
109
|
requirements:
|
125
110
|
- - ">="
|
126
111
|
- !ruby/object:Gem::Version
|
127
|
-
hash:
|
112
|
+
hash: 1216210944947938384
|
128
113
|
segments:
|
129
114
|
- 0
|
130
115
|
version: "0"
|
@@ -133,14 +118,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
133
118
|
requirements:
|
134
119
|
- - ">="
|
135
120
|
- !ruby/object:Gem::Version
|
136
|
-
hash:
|
121
|
+
hash: 1216210944947938384
|
137
122
|
segments:
|
138
123
|
- 0
|
139
124
|
version: "0"
|
140
125
|
requirements: []
|
141
126
|
|
142
127
|
rubyforge_project:
|
143
|
-
rubygems_version: 1.
|
128
|
+
rubygems_version: 1.6.2
|
144
129
|
signing_key:
|
145
130
|
specification_version: 3
|
146
131
|
summary: A tree structure for Mongoid documents
|