mongoid-tree 0.4.0 → 0.5.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 +7 -2
- data/lib/mongoid/tree/ordering.rb +33 -7
- data/lib/mongoid/tree/traversal.rb +36 -2
- data/lib/mongoid/tree.rb +10 -3
- data/spec/mongoid/tree/ordering_spec.rb +13 -6
- data/spec/mongoid/tree/traversal_spec.rb +63 -2
- data/spec/mongoid/tree_spec.rb +18 -14
- data/spec/support/macros/tree_macros.rb +9 -14
- data/spec/support/models/node.rb +2 -0
- metadata +8 -9
- data/Gemfile.lock +0 -57
data/README.rdoc
CHANGED
@@ -156,12 +156,17 @@ Example:
|
|
156
156
|
|
157
157
|
== Known issues
|
158
158
|
|
159
|
-
See
|
159
|
+
See https://github.com/benedikt/mongoid-tree/issues
|
160
160
|
|
161
161
|
|
162
162
|
== Repository
|
163
163
|
|
164
|
-
See
|
164
|
+
See https://github.com/benedikt/mongoid-tree and feel free to fork it!
|
165
|
+
|
166
|
+
|
167
|
+
== Contributors
|
168
|
+
|
169
|
+
See a list of all contributors at https://github.com/benedikt/mongoid-tree/contributors. Thanks a lot everyone!
|
165
170
|
|
166
171
|
|
167
172
|
== Copyright
|
@@ -38,10 +38,22 @@ module Mongoid
|
|
38
38
|
field :position, :type => Integer
|
39
39
|
|
40
40
|
before_save :assign_default_position
|
41
|
-
before_save :reposition_former_siblings, :if => :
|
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
|
+
|
45
57
|
##
|
46
58
|
# Returns siblings below the current document.
|
47
59
|
# Siblings with a position greater than this documents's position.
|
@@ -115,17 +127,22 @@ module Mongoid
|
|
115
127
|
#
|
116
128
|
# This method changes the node's parent if nescessary.
|
117
129
|
def move_above(other)
|
118
|
-
|
130
|
+
unless sibling_of?(other)
|
131
|
+
self.parent_id = other.parent_id
|
132
|
+
save!
|
133
|
+
end
|
119
134
|
|
120
135
|
if position > other.position
|
121
136
|
new_position = other.position
|
122
137
|
other.lower_siblings.where(:position.lt => self.position).each { |s| s.inc(:position, 1) }
|
123
138
|
other.inc(:position, 1)
|
124
|
-
|
139
|
+
self.position = new_position
|
140
|
+
save!
|
125
141
|
else
|
126
142
|
new_position = other.position - 1
|
127
143
|
other.higher_siblings.where(:position.gt => self.position).each { |s| s.inc(:position, -1) }
|
128
|
-
|
144
|
+
self.position = new_position
|
145
|
+
save!
|
129
146
|
end
|
130
147
|
end
|
131
148
|
|
@@ -134,17 +151,22 @@ module Mongoid
|
|
134
151
|
#
|
135
152
|
# This method changes the node's parent if nescessary.
|
136
153
|
def move_below(other)
|
137
|
-
|
154
|
+
unless sibling_of?(other)
|
155
|
+
self.parent_id = other.parent_id
|
156
|
+
save!
|
157
|
+
end
|
138
158
|
|
139
159
|
if position > other.position
|
140
160
|
new_position = other.position + 1
|
141
161
|
other.lower_siblings.where(:position.lt => self.position).each { |s| s.inc(:position, 1) }
|
142
|
-
|
162
|
+
self.position = new_position
|
163
|
+
save!
|
143
164
|
else
|
144
165
|
new_position = other.position
|
145
166
|
other.higher_siblings.where(:position.gt => self.position).each { |s| s.inc(:position, -1) }
|
146
167
|
other.inc(:position, -1)
|
147
|
-
|
168
|
+
self.position = new_position
|
169
|
+
save!
|
148
170
|
end
|
149
171
|
end
|
150
172
|
|
@@ -161,6 +183,10 @@ module Mongoid
|
|
161
183
|
former_siblings.each { |s| s.inc(:position, -1) }
|
162
184
|
end
|
163
185
|
|
186
|
+
def sibling_reposition_required?
|
187
|
+
parent_id_changed? && persisted?
|
188
|
+
end
|
189
|
+
|
164
190
|
def assign_default_position
|
165
191
|
return unless self.position.nil? || self.parent_id_changed?
|
166
192
|
|
@@ -46,6 +46,41 @@ module Mongoid # :nodoc:
|
|
46
46
|
# node1, node2, node3, node4, node5, node6, node7
|
47
47
|
#
|
48
48
|
module Traversal
|
49
|
+
extend ActiveSupport::Concern
|
50
|
+
|
51
|
+
##
|
52
|
+
# :singleton-method: traverse
|
53
|
+
# Traverses the entire tree, one root at a time, using the given traversal
|
54
|
+
# method (Default is :depth_first).
|
55
|
+
#
|
56
|
+
# See Mongoid::Tree::Traversal for available traversal methods.
|
57
|
+
#
|
58
|
+
# Example:
|
59
|
+
#
|
60
|
+
# # Say we have the following tree, and want to print its hierarchy:
|
61
|
+
# # root_1
|
62
|
+
# # child_1_a
|
63
|
+
# # root_2
|
64
|
+
# # child_2_a
|
65
|
+
# # child_2_a_1
|
66
|
+
#
|
67
|
+
# Node.traverse(:depth_first) do |node|
|
68
|
+
# indentation = ' ' * node.depth
|
69
|
+
#
|
70
|
+
# puts "#{indentation}#{node.name}"
|
71
|
+
# end
|
72
|
+
#
|
73
|
+
|
74
|
+
##
|
75
|
+
# The methods in this module are class-level methods documented above.
|
76
|
+
# They're extended into the base class automatically.
|
77
|
+
module ClassMethods # :nodoc:
|
78
|
+
def traverse(type = :depth_first, &block)
|
79
|
+
raise ArgumentError, "No block given" unless block_given?
|
80
|
+
roots.each { |root| root.traverse(type, &block) }
|
81
|
+
nil
|
82
|
+
end
|
83
|
+
end
|
49
84
|
|
50
85
|
##
|
51
86
|
# Traverses the tree using the given traversal method (Default is :depth_first)
|
@@ -60,7 +95,7 @@ module Mongoid # :nodoc:
|
|
60
95
|
# results << node
|
61
96
|
# end
|
62
97
|
def traverse(type = :depth_first, &block)
|
63
|
-
raise "No block given" unless block_given?
|
98
|
+
raise ArgumentError, "No block given" unless block_given?
|
64
99
|
send("#{type}_traversal", &block)
|
65
100
|
end
|
66
101
|
|
@@ -79,7 +114,6 @@ module Mongoid # :nodoc:
|
|
79
114
|
queue += node.children
|
80
115
|
end
|
81
116
|
end
|
82
|
-
|
83
117
|
end
|
84
118
|
end
|
85
119
|
end
|
data/lib/mongoid/tree.rb
CHANGED
@@ -84,8 +84,12 @@ module Mongoid # :nodoc:
|
|
84
84
|
|
85
85
|
included do
|
86
86
|
references_many :children, :class_name => self.name, :foreign_key => :parent_id, :inverse_of => :parent do
|
87
|
-
def <<(*objects)
|
88
|
-
super
|
87
|
+
def <<(*objects) # :nodoc:
|
88
|
+
super
|
89
|
+
objects.each do |c|
|
90
|
+
c.parent = @parent
|
91
|
+
c.save
|
92
|
+
end
|
89
93
|
end
|
90
94
|
end
|
91
95
|
|
@@ -274,7 +278,10 @@ module Mongoid # :nodoc:
|
|
274
278
|
##
|
275
279
|
# Moves all children to this document's parent
|
276
280
|
def move_children_to_parent
|
277
|
-
children.each
|
281
|
+
children.each do |c|
|
282
|
+
c.parent_id = self.parent_id
|
283
|
+
c.save
|
284
|
+
end
|
278
285
|
end
|
279
286
|
|
280
287
|
##
|
@@ -2,6 +2,8 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Mongoid::Tree::Ordering do
|
4
4
|
|
5
|
+
subject { OrderedNode }
|
6
|
+
|
5
7
|
it "should store position as an Integer with a default of nil" do
|
6
8
|
f = OrderedNode.fields['position']
|
7
9
|
f.should_not be_nil
|
@@ -11,7 +13,7 @@ describe Mongoid::Tree::Ordering do
|
|
11
13
|
|
12
14
|
describe 'when saved' do
|
13
15
|
before(:each) do
|
14
|
-
|
16
|
+
setup_tree <<-ENDTREE
|
15
17
|
- root:
|
16
18
|
- child:
|
17
19
|
- subchild:
|
@@ -60,11 +62,18 @@ describe Mongoid::Tree::Ordering do
|
|
60
62
|
other_child.save!
|
61
63
|
node(:another_child).position.should == 0
|
62
64
|
end
|
65
|
+
|
66
|
+
it "should not reposition siblings when it's not yet saved" do
|
67
|
+
new_node = OrderedNode.new(:name => 'new')
|
68
|
+
new_node.parent = node(:root)
|
69
|
+
new_node.should_not_receive(:reposition_former_siblings)
|
70
|
+
new_node.save
|
71
|
+
end
|
63
72
|
end
|
64
73
|
|
65
74
|
describe 'destroy strategies' do
|
66
75
|
before(:each) do
|
67
|
-
|
76
|
+
setup_tree <<-ENDTREE
|
68
77
|
- root:
|
69
78
|
- child:
|
70
79
|
- subchild
|
@@ -84,7 +93,7 @@ describe Mongoid::Tree::Ordering do
|
|
84
93
|
|
85
94
|
describe 'utility methods' do
|
86
95
|
before(:each) do
|
87
|
-
|
96
|
+
setup_tree <<-ENDTREE
|
88
97
|
- first_root:
|
89
98
|
- first_child_of_first_root
|
90
99
|
- second_child_of_first_root
|
@@ -159,7 +168,7 @@ describe Mongoid::Tree::Ordering do
|
|
159
168
|
|
160
169
|
describe 'moving nodes around', :focus => true do
|
161
170
|
before(:each) do
|
162
|
-
|
171
|
+
setup_tree <<-ENDTREE
|
163
172
|
- first_root:
|
164
173
|
- first_child_of_first_root
|
165
174
|
- second_child_of_first_root
|
@@ -175,7 +184,6 @@ describe Mongoid::Tree::Ordering do
|
|
175
184
|
describe '#move_below' do
|
176
185
|
it 'should fix positions within the current list when moving an sibling away from its current parent' do
|
177
186
|
node_to_move = node(:first_child_of_first_root)
|
178
|
-
new_parent = node(:second_root)
|
179
187
|
node_to_move.move_below(node(:first_child_of_second_root))
|
180
188
|
node(:second_child_of_first_root).position.should == 0
|
181
189
|
end
|
@@ -214,7 +222,6 @@ describe Mongoid::Tree::Ordering do
|
|
214
222
|
describe '#move_above' do
|
215
223
|
it 'should fix positions within the current list when moving an sibling away from its current parent' do
|
216
224
|
node_to_move = node(:first_child_of_first_root)
|
217
|
-
new_parent = node(:second_root)
|
218
225
|
node_to_move.move_above(node(:first_child_of_second_root))
|
219
226
|
node(:second_child_of_first_root).position.should == 0
|
220
227
|
end
|
@@ -2,6 +2,8 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Mongoid::Tree::Traversal do
|
4
4
|
|
5
|
+
subject { Node }
|
6
|
+
|
5
7
|
describe '#traverse' do
|
6
8
|
|
7
9
|
subject { Node.new }
|
@@ -10,7 +12,7 @@ describe Mongoid::Tree::Traversal do
|
|
10
12
|
expect { subject.traverse }.to raise_error(/No block given/)
|
11
13
|
end
|
12
14
|
|
13
|
-
[:depth_first].each do |method|
|
15
|
+
[:depth_first, :breadth_first].each do |method|
|
14
16
|
it "should support #{method} traversal" do
|
15
17
|
expect { subject.traverse(method) {} }.to_not raise_error
|
16
18
|
end
|
@@ -68,8 +70,11 @@ describe Mongoid::Tree::Traversal do
|
|
68
70
|
end
|
69
71
|
|
70
72
|
describe 'with reordered nodes' do
|
73
|
+
|
74
|
+
subject { OrderedNode }
|
75
|
+
|
71
76
|
before do
|
72
|
-
|
77
|
+
setup_tree <<-ENDTREE
|
73
78
|
node1:
|
74
79
|
- node2:
|
75
80
|
- node3
|
@@ -111,4 +116,60 @@ describe Mongoid::Tree::Traversal do
|
|
111
116
|
|
112
117
|
end
|
113
118
|
|
119
|
+
describe '.traverse' do
|
120
|
+
|
121
|
+
describe 'when not given a block' do
|
122
|
+
|
123
|
+
it 'raises an error' do
|
124
|
+
expect {Node.traverse}.to raise_error ArgumentError, 'No block given'
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
before :each do
|
129
|
+
setup_tree <<-ENDTREE
|
130
|
+
- root1
|
131
|
+
- root2
|
132
|
+
ENDTREE
|
133
|
+
|
134
|
+
@block = Proc.new {}
|
135
|
+
@root1 = node(:root1)
|
136
|
+
@root2 = node(:root2)
|
137
|
+
|
138
|
+
Node.stub(:roots).and_return [@root1, @root2]
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'grabs each root' do
|
142
|
+
Node.should_receive(:roots).and_return []
|
143
|
+
|
144
|
+
Node.traverse &@block
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'defaults the "type" arg to :depth_first' do
|
148
|
+
@root1.should_receive(:traverse).with(:depth_first)
|
149
|
+
@root2.should_receive(:traverse).with(:depth_first)
|
150
|
+
|
151
|
+
Node.traverse &@block
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'traverses each root' do
|
155
|
+
@root1.should_receive(:traverse)
|
156
|
+
@root2.should_receive(:traverse)
|
157
|
+
|
158
|
+
Node.traverse &@block
|
159
|
+
end
|
160
|
+
|
161
|
+
describe 'when the "type" arg is :breadth_first' do
|
162
|
+
|
163
|
+
it 'traverses breadth-first' do
|
164
|
+
@root1.should_receive(:traverse).with(:breadth_first)
|
165
|
+
@root2.should_receive(:traverse).with(:breadth_first)
|
166
|
+
|
167
|
+
Node.traverse :breadth_first, &@block
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'returns nil' do
|
172
|
+
Node.traverse(&@block).should be nil
|
173
|
+
end
|
174
|
+
end
|
114
175
|
end
|
data/spec/mongoid/tree_spec.rb
CHANGED
@@ -2,29 +2,31 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Mongoid::Tree do
|
4
4
|
|
5
|
+
subject { Node }
|
6
|
+
|
5
7
|
it "should reference many children as inverse of parent with index" do
|
6
|
-
a = Node.
|
7
|
-
a.
|
8
|
-
a.association.should
|
9
|
-
a.options.class_name.should
|
10
|
-
a.options.foreign_key.should
|
8
|
+
a = Node.reflect_on_association(:children)
|
9
|
+
a.should be
|
10
|
+
a.association.should eql(Mongoid::Associations::ReferencesMany)
|
11
|
+
a.options.class_name.should eql('Node')
|
12
|
+
a.options.foreign_key.should eql('parent_id')
|
11
13
|
Node.index_options.should have_key('parent_id')
|
12
14
|
end
|
13
15
|
|
14
16
|
it "should be referenced in one parent as inverse of children" do
|
15
|
-
a = Node.
|
16
|
-
a.
|
17
|
-
a.association.should
|
18
|
-
a.options.class_name.should
|
19
|
-
a.options.inverse_of.should
|
17
|
+
a = Node.reflect_on_association(:parent)
|
18
|
+
a.should be
|
19
|
+
a.association.should eql(Mongoid::Associations::ReferencedIn)
|
20
|
+
a.options.class_name.should eql('Node')
|
21
|
+
a.options.inverse_of.should eql(:children)
|
20
22
|
a.options.index.should be_true
|
21
23
|
end
|
22
24
|
|
23
25
|
it "should store parent_ids as Array with [] as default with index" do
|
24
26
|
f = Node.fields['parent_ids']
|
25
|
-
f.
|
26
|
-
f.options[:type].should
|
27
|
-
f.options[:default].should
|
27
|
+
f.should be
|
28
|
+
f.options[:type].should eql(Array)
|
29
|
+
f.options[:default].should eql([])
|
28
30
|
Node.index_options.should have_key(:parent_ids)
|
29
31
|
end
|
30
32
|
|
@@ -84,7 +86,9 @@ describe Mongoid::Tree do
|
|
84
86
|
end
|
85
87
|
|
86
88
|
it "should rebuild its children's parent_ids when its own parent_id is removed" do
|
87
|
-
node(:child)
|
89
|
+
c = node(:child)
|
90
|
+
c.parent_id = nil
|
91
|
+
c.save
|
88
92
|
node(:subchild).parent_ids.should == [node(:child).id]
|
89
93
|
end
|
90
94
|
|
@@ -3,11 +3,7 @@ require 'yaml'
|
|
3
3
|
module Mongoid::Tree::TreeMacros
|
4
4
|
|
5
5
|
def setup_tree(tree)
|
6
|
-
create_tree(YAML.load(tree)
|
7
|
-
end
|
8
|
-
|
9
|
-
def setup_ordered_tree(tree)
|
10
|
-
create_tree(YAML.load(tree), {:ordered => true})
|
6
|
+
create_tree(YAML.load(tree))
|
11
7
|
end
|
12
8
|
|
13
9
|
def node(name)
|
@@ -25,22 +21,21 @@ module Mongoid::Tree::TreeMacros
|
|
25
21
|
end
|
26
22
|
|
27
23
|
private
|
28
|
-
def create_tree(object
|
24
|
+
def create_tree(object)
|
29
25
|
case object
|
30
|
-
when String
|
31
|
-
when Array
|
32
|
-
when Hash
|
26
|
+
when String then return create_node(object)
|
27
|
+
when Array then object.each { |tree| create_tree(tree) }
|
28
|
+
when Hash then
|
33
29
|
name, children = object.first
|
34
|
-
node = create_node(name
|
35
|
-
children.each { |c| node.children << create_tree(c
|
30
|
+
node = create_node(name)
|
31
|
+
children.each { |c| node.children << create_tree(c) }
|
36
32
|
return node
|
37
33
|
end
|
38
34
|
end
|
39
35
|
|
40
|
-
def create_node(name
|
41
|
-
node_class = opts[:ordered] ? OrderedNode : Node
|
36
|
+
def create_node(name)
|
42
37
|
@nodes ||= HashWithIndifferentAccess.new
|
43
|
-
@nodes[name] =
|
38
|
+
@nodes[name] = subject.create(:name => name)
|
44
39
|
end
|
45
40
|
end
|
46
41
|
|
data/spec/support/models/node.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongoid-tree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 11
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 5
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.5.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Benedikt Deicke
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-
|
18
|
+
date: 2010-12-20 00:00:00 +01:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -44,11 +44,11 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - ~>
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
hash:
|
47
|
+
hash: 5
|
48
48
|
segments:
|
49
49
|
- 2
|
50
|
-
-
|
51
|
-
version: "2.
|
50
|
+
- 3
|
51
|
+
version: "2.3"
|
52
52
|
type: :development
|
53
53
|
version_requirements: *id002
|
54
54
|
- !ruby/object:Gem::Dependency
|
@@ -107,10 +107,9 @@ files:
|
|
107
107
|
- README.rdoc
|
108
108
|
- Rakefile
|
109
109
|
- Gemfile
|
110
|
-
- Gemfile.lock
|
111
110
|
- .rspec
|
112
111
|
has_rdoc: true
|
113
|
-
homepage:
|
112
|
+
homepage: https://github.com/benedikt/mongoid-tree
|
114
113
|
licenses: []
|
115
114
|
|
116
115
|
post_install_message:
|
data/Gemfile.lock
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
mongoid-tree (0.4.0)
|
5
|
-
mongoid (>= 2.0.0.beta.20)
|
6
|
-
|
7
|
-
GEM
|
8
|
-
remote: http://rubygems.org/
|
9
|
-
specs:
|
10
|
-
activemodel (3.0.1)
|
11
|
-
activesupport (= 3.0.1)
|
12
|
-
builder (~> 2.1.2)
|
13
|
-
i18n (~> 0.4.1)
|
14
|
-
activesupport (3.0.1)
|
15
|
-
autotest (4.4.2)
|
16
|
-
bson (1.1.1)
|
17
|
-
bson_ext (1.1.1)
|
18
|
-
builder (2.1.2)
|
19
|
-
diff-lcs (1.1.2)
|
20
|
-
haml (2.2.24)
|
21
|
-
hanna (0.1.12)
|
22
|
-
haml (~> 2.2.8)
|
23
|
-
rake (~> 0.8.2)
|
24
|
-
rdoc (~> 2.3.0)
|
25
|
-
i18n (0.4.2)
|
26
|
-
mongo (1.1.1)
|
27
|
-
bson (>= 1.1.1)
|
28
|
-
mongoid (2.0.0.beta.20)
|
29
|
-
activemodel (~> 3.0)
|
30
|
-
mongo (~> 1.1)
|
31
|
-
tzinfo (~> 0.3.22)
|
32
|
-
will_paginate (~> 3.0.pre)
|
33
|
-
rake (0.8.7)
|
34
|
-
rdoc (2.3.0)
|
35
|
-
rspec (2.0.1)
|
36
|
-
rspec-core (~> 2.0.1)
|
37
|
-
rspec-expectations (~> 2.0.1)
|
38
|
-
rspec-mocks (~> 2.0.1)
|
39
|
-
rspec-core (2.0.1)
|
40
|
-
rspec-expectations (2.0.1)
|
41
|
-
diff-lcs (>= 1.1.2)
|
42
|
-
rspec-mocks (2.0.1)
|
43
|
-
rspec-core (~> 2.0.1)
|
44
|
-
rspec-expectations (~> 2.0.1)
|
45
|
-
tzinfo (0.3.23)
|
46
|
-
will_paginate (3.0.pre2)
|
47
|
-
|
48
|
-
PLATFORMS
|
49
|
-
ruby
|
50
|
-
|
51
|
-
DEPENDENCIES
|
52
|
-
autotest (>= 4.3.2)
|
53
|
-
bson_ext (>= 1.0.4)
|
54
|
-
hanna (>= 0.1.12)
|
55
|
-
mongoid (>= 2.0.0.beta.20)
|
56
|
-
mongoid-tree!
|
57
|
-
rspec (~> 2.0)
|