mongoid-tree 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source :rubygems
2
+
3
+ gemspec
4
+
5
+ gem 'bson_ext', '>= 1.0.4'
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Benedikt Deicke
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,44 @@
1
+ = mongoid-tree
2
+
3
+ A tree structure for Mongoid documents using the materialized path pattern
4
+
5
+ == Requirements
6
+
7
+ * mongoid (>= 2.0.0.beta9)
8
+
9
+ == Install
10
+
11
+ To install mongoid_tree, simply add it to your Gemfile:
12
+
13
+ gem "mongoid-tree"
14
+
15
+ In order to get the latest development version of mongoid-tree:
16
+
17
+ gem "mongoid-tree" :git => "git://github.com/benedikt/mongoid-tree"
18
+
19
+ You might want to add the <tt>:require => 'mongoid/tree'</tt> option as well and finally run
20
+
21
+ bundle install
22
+
23
+ == Usage
24
+
25
+ Read the API documentation at http://benedikt.github.com/mongoid-tree and take a look at the Mongoid::Tree module
26
+
27
+ require 'mongoid/tree'
28
+
29
+ class Node
30
+ include Mongoid::Document
31
+ include Mongoid::Tree
32
+ end
33
+
34
+ == Known issues
35
+
36
+ See http://github.com/benedikt/mongoid-tree/issues
37
+
38
+ == Repository
39
+
40
+ See http://github.com/benedikt/mongoid-tree and feel free to fork it!
41
+
42
+ == Copyright
43
+
44
+ Copyright (c) 2010 Benedikt Deicke. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,26 @@
1
+ require 'rspec/core/rake_task'
2
+ require 'hanna/rdoctask'
3
+
4
+ spec = Gem::Specification.load("mongoid-tree.gemspec")
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task :default => :spec
9
+
10
+ Rake::RDocTask.new do |rdoc|
11
+ rdoc.rdoc_dir = 'doc'
12
+ rdoc.title = "#{spec.name} #{spec.version}"
13
+ rdoc.options += spec.rdoc_options
14
+ rdoc.rdoc_files.include(spec.extra_rdoc_files)
15
+ rdoc.rdoc_files.include('lib/**/*.rb')
16
+ end
17
+
18
+ desc "Build the .gem file"
19
+ task :build do
20
+ system "gem build #{spec.name}.gemspec"
21
+ end
22
+
23
+ desc "Push the .gem file to rubygems.org"
24
+ task :release => :build do
25
+ system "gem push #{spec.name}-#{spec.version}.gem"
26
+ end
@@ -0,0 +1,157 @@
1
+ require 'mongoid/tree/traversal'
2
+
3
+ module Mongoid # :nodoc:
4
+ ##
5
+ # = Mongoid::Tree
6
+ #
7
+ # This module extends any Mongoid document with tree functionality.
8
+ #
9
+ # == Usage
10
+ #
11
+ # Simply include the module in any Mongoid document:
12
+ #
13
+ # class Node
14
+ # include Mongoid::Document
15
+ # include Mongoid::Tree
16
+ # end
17
+ #
18
+ # === Using the tree structure
19
+ #
20
+ # Each document references many children. You can access them using the <tt>#children</tt> method.
21
+ #
22
+ # node = Node.create
23
+ # node.children.create
24
+ # node.children.count # => 1
25
+ #
26
+ # Every document references one parent (unless it's a root document).
27
+ #
28
+ # node = Node.create
29
+ # node.parent # => nil
30
+ # node.children.create
31
+ # node.children.first.parent # => node
32
+ #
33
+ module Tree
34
+ extend ActiveSupport::Concern
35
+
36
+ include Traversal
37
+
38
+ included do
39
+ reference_many :children, :class_name => self.name, :foreign_key => :parent_id, :inverse_of => :parent
40
+ referenced_in :parent, :class_name => self.name, :inverse_of => :children
41
+
42
+ field :parent_ids, :type => Array, :default => []
43
+
44
+ set_callback :validation, :before, :rearrange
45
+ set_callback :save, :after, :rearrange_children, :if => :rearrange_children?
46
+ end
47
+
48
+ ##
49
+ # :method: children
50
+ # Returns a list of the document's children. It's a <tt>reference_many</tt> association.
51
+ # (Generated by Mongoid)
52
+
53
+ ##
54
+ # :method: parent
55
+ # Returns the document's parent (unless it's a root document). It's a <tt>referenced_in</tt> association.
56
+ # (Generated by Mongoid)
57
+
58
+ ##
59
+ # :method: parent_ids
60
+ # Returns a list of the document's parent_ids, starting with the root node.
61
+ # (Generated by Mongoid)
62
+
63
+ ##
64
+ # Is this document a root node (has no parent)?
65
+ def root?
66
+ parent_id.nil?
67
+ end
68
+
69
+ ##
70
+ # Is this document a leaf node (has no children)?
71
+ def leaf?
72
+ children.empty?
73
+ end
74
+
75
+ ##
76
+ # Returns this document's root node
77
+ def root
78
+ self.class.find(parent_ids.first)
79
+ end
80
+
81
+ ##
82
+ # Returns this document's ancestors
83
+ def ancestors
84
+ self.class.find(:conditions => { :_id.in => parent_ids })
85
+ end
86
+
87
+ ##
88
+ # Returns this document's ancestors and itself
89
+ def ancestors_and_self
90
+ ancestors + [self]
91
+ end
92
+
93
+ ##
94
+ # Is this document an ancestor of the other document?
95
+ def ancestor_of?(other)
96
+ other.parent_ids.include?(self.id)
97
+ end
98
+
99
+ ##
100
+ # Returns this document's descendants
101
+ def descendants
102
+ self.class.find(:conditions => { :parent_ids => self.id })
103
+ end
104
+
105
+ ##
106
+ # Returns this document's descendants and itself
107
+ def descendants_and_self
108
+ [self] + descendants
109
+ end
110
+
111
+ ##
112
+ # Is this document a descendant of the other document?
113
+ def descendant_of?(other)
114
+ self.parent_ids.include?(other.id)
115
+ end
116
+
117
+ ##
118
+ # Returns this document's siblings
119
+ def siblings
120
+ siblings_and_self - [self]
121
+ end
122
+
123
+ ##
124
+ # Returns this document's siblings and itself
125
+ def siblings_and_self
126
+ self.class.find(:conditions => { :parent_id => self.parent_id })
127
+ end
128
+
129
+ ##
130
+ # Forces rearranging of all children after next save
131
+ def rearrange_children!
132
+ @rearrange_children = true
133
+ end
134
+
135
+ ##
136
+ # Will the children be rearranged after next save?
137
+ def rearrange_children?
138
+ !!@rearrange_children
139
+ end
140
+
141
+ private
142
+
143
+ def rearrange
144
+ if self.parent_id
145
+ self.parent_ids = self.class.find(self.parent_id).parent_ids + [self.parent_id]
146
+ end
147
+
148
+ rearrange_children! if self.parent_ids_changed?
149
+ return true
150
+ end
151
+
152
+ def rearrange_children
153
+ @rearrange_children = false
154
+ self.children.find(:all).each { |c| c.save }
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,85 @@
1
+ module Mongoid # :nodoc:
2
+ module Tree
3
+ ##
4
+ # = Mongoid::Tree::Traversal
5
+ #
6
+ # Mongoid::Tree provides a #traverse method to walk through the tree.
7
+ # It supports these traversal methods:
8
+ #
9
+ # * depth_first
10
+ # * breadth_first
11
+ #
12
+ # == Depth First Traversal
13
+ #
14
+ # See http://en.wikipedia.org/wiki/Depth-first_search for a proper description.
15
+ #
16
+ # Given a tree like:
17
+ #
18
+ # node1:
19
+ # - node2:
20
+ # - node3
21
+ # - node4:
22
+ # - node5
23
+ # - node6
24
+ # - node7
25
+ #
26
+ # Traversing the tree using depth first traversal would visit each node in this order:
27
+ #
28
+ # node1, node2, node3, node4, node5, node6, node7
29
+ #
30
+ # == Breadth First Traversal
31
+ #
32
+ # See http://en.wikipedia.org/wiki/Breadth-first_search for a proper description.
33
+ #
34
+ # Given a tree like:
35
+ #
36
+ # node1:
37
+ # - node2:
38
+ # - node5
39
+ # - node3:
40
+ # - node6
41
+ # - node7
42
+ # - node4
43
+ #
44
+ # Traversing the tree using breadth first traversal would visit each node in this order:
45
+ #
46
+ # node1, node2, node3, node4, node5, node6, node7
47
+ #
48
+ module Traversal
49
+
50
+ ##
51
+ # Traverses the tree using the given traversal method (Default is :depth_first)
52
+ # and passes each document node to the block.
53
+ #
54
+ # See Mongoid::Tree::Traversal for available traversal methods.
55
+ #
56
+ # Example:
57
+ #
58
+ # results = []
59
+ # root.traverse(:depth_first) do |node|
60
+ # results << node
61
+ # end
62
+ def traverse(type = :depth_first, &block)
63
+ raise "No block given" unless block_given?
64
+ send("#{type}_traversal", &block)
65
+ end
66
+
67
+ private
68
+
69
+ def depth_first_traversal(&block)
70
+ block.call(self)
71
+ self.children.each { |c| c.send(:depth_first_traversal, &block) }
72
+ end
73
+
74
+ def breadth_first_traversal(&block)
75
+ queue = [self]
76
+ while queue.any? do
77
+ node = queue.shift
78
+ block.call(node)
79
+ queue += node.children
80
+ end
81
+ end
82
+
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,92 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongoid::Tree::Traversal do
4
+
5
+ describe '#traverse' do
6
+
7
+ subject { Node.new }
8
+
9
+ it "should require a block" do
10
+ expect { subject.traverse }.to raise_error(/No block given/)
11
+ end
12
+
13
+ [:depth_first].each do |method|
14
+ it "should support #{method} traversal" do
15
+ expect { subject.traverse(method) {} }.to_not raise_error
16
+ end
17
+ end
18
+
19
+ it "should complain about unsupported traversal methods" do
20
+ expect { subject.traverse('non_existing') {} }.to raise_error
21
+ end
22
+
23
+ it "should default to depth_first traversal" do
24
+ subject.should_receive(:depth_first_traversal)
25
+ subject.traverse {}
26
+ end
27
+
28
+ end
29
+
30
+ describe 'depth first traversal' do
31
+
32
+ it "should traverse correctly" do
33
+ setup_tree <<-ENDTREE
34
+ node1:
35
+ - node2:
36
+ - node3
37
+ - node4:
38
+ - node5
39
+ - node6
40
+ - node7
41
+ ENDTREE
42
+
43
+ result = []
44
+ node(:node1).traverse(:depth_first) { |node| result << node }
45
+ result.collect { |n| n.name.to_sym }.should == [:node1, :node2, :node3, :node4, :node5, :node6, :node7]
46
+ end
47
+
48
+ it "should traverse correctly on merged trees" do
49
+
50
+ setup_tree <<-ENDTREE
51
+ - node4:
52
+ - node5
53
+ - node6:
54
+ - node7
55
+
56
+ - node1:
57
+ - node2:
58
+ - node3
59
+ ENDTREE
60
+
61
+
62
+ node(:node1).children << node(:node4)
63
+
64
+
65
+ result = []
66
+ node(:node1).traverse(:depth_first) { |node| result << node }
67
+ result.collect { |n| n.name.to_sym }.should == [:node1, :node2, :node3, :node4, :node5, :node6, :node7]
68
+ end
69
+
70
+ end
71
+
72
+ describe 'breadth first traversal' do
73
+
74
+ it "should traverse correctly" do
75
+ tree = setup_tree <<-ENDTREE
76
+ node1:
77
+ - node2:
78
+ - node5
79
+ - node3:
80
+ - node6
81
+ - node7
82
+ - node4
83
+ ENDTREE
84
+
85
+ result = []
86
+ node(:node1).traverse(:breadth_first) { |n| result << n }
87
+ result.collect { |n| n.name.to_sym }.should == [:node1, :node2, :node3, :node4, :node5, :node6, :node7]
88
+ end
89
+
90
+ end
91
+
92
+ end
@@ -0,0 +1,178 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongoid::Tree do
4
+
5
+ it "should reference many children as inverse of parent" do
6
+ a = Node.associations['children']
7
+ a.should_not be_nil
8
+ a.association.should == Mongoid::Associations::ReferencesMany
9
+ a.options.class_name.should == 'Node'
10
+ a.options.foreign_key.should == 'parent_id'
11
+ a.options.inverse_of.should == :parent
12
+ end
13
+
14
+ it "should be referenced in one parent as inverse of children" do
15
+ a = Node.associations['parent']
16
+ a.should_not be_nil
17
+ a.association.should == Mongoid::Associations::ReferencedIn
18
+ a.options.class_name.should == 'Node'
19
+ a.options.inverse_of.should == :children
20
+ end
21
+
22
+ it "should store parent_ids as Array with [] as default" do
23
+ f = Node.fields['parent_ids']
24
+ f.should_not be_nil
25
+ f.options[:type].should == Array
26
+ f.options[:default].should == []
27
+ end
28
+
29
+ describe 'when saved' do
30
+
31
+ before(:each) do
32
+ setup_tree <<-ENDTREE
33
+ - root:
34
+ - child:
35
+ - subchild:
36
+ - subsubchild
37
+ - other_root:
38
+ - other_child
39
+ ENDTREE
40
+ end
41
+
42
+ it "should set the child's parent_id when added to parent's children" do
43
+ root = Node.create; child = Node.create
44
+ root.children << child
45
+ child.parent.should == root
46
+ child.parent_id.should == root.id
47
+ end
48
+
49
+ it "should set the child's parent_id parent is set on child" do
50
+ root = Node.create; child = Node.create
51
+ child.parent = root
52
+ child.parent.should == root
53
+ child.parent_id.should == root.id
54
+ end
55
+
56
+ it "should rebuild its parent_ids" do
57
+ root = Node.create; child = Node.create
58
+ root.children << child
59
+ child.parent_ids.should == [root.id]
60
+ end
61
+
62
+ it "should rebuild its children's parent_ids when its own parent_ids changed" do
63
+ other_root = node(:other_root); child = node(:child); subchild = node(:subchild);
64
+ other_root.children << child
65
+ subchild.reload # To get the updated version
66
+ subchild.parent_ids.should == [other_root.id, child.id]
67
+ end
68
+
69
+ it "should correctly rebuild its descendants' parent_ids when moved into an other subtree" do
70
+ subchild = node(:subchild); subsubchild = node(:subsubchild); other_child = node(:other_child)
71
+ other_child.children << subchild
72
+ subsubchild.reload
73
+ subsubchild.parent_ids.should == [node(:other_root).id, other_child.id, subchild.id]
74
+ end
75
+
76
+ it "should not rebuild its children's parent_ids when it's not required" do
77
+ root = node(:root)
78
+ root.should_not_receive(:rearrange_children)
79
+ root.save
80
+ end
81
+
82
+ end
83
+
84
+ describe 'utility methods' do
85
+
86
+ before(:each) do
87
+ setup_tree <<-ENDTREE
88
+ root:
89
+ - child:
90
+ - subchild
91
+ - other_child
92
+ ENDTREE
93
+ end
94
+
95
+ describe '.root?' do
96
+ it "should return true for root documents" do
97
+ node(:root).should be_root
98
+ end
99
+
100
+ it "should return false for non-root documents" do
101
+ node(:child).should_not be_root
102
+ end
103
+ end
104
+
105
+ describe '.leaf?' do
106
+ it "should return true for leaf documents" do
107
+ node(:subchild).should be_leaf
108
+ node(:other_child).should be_leaf
109
+ Node.new.should be_leaf
110
+ end
111
+
112
+ it "should return false for non-leaf documents" do
113
+ node(:child).should_not be_leaf
114
+ node(:root).should_not be_leaf
115
+ end
116
+ end
117
+
118
+ describe '.root' do
119
+ it "should return the root for this document" do
120
+ node(:subchild).root.should == node(:root)
121
+ end
122
+ end
123
+
124
+ describe 'ancestors' do
125
+ it ".ancestors should return the documents ancestors" do
126
+ node(:subchild).ancestors.to_a.should == [node(:root), node(:child)]
127
+ end
128
+
129
+ it ".ancestors_and_self should return the documents ancestors and itself" do
130
+ node(:subchild).ancestors_and_self.to_a.should == [node(:root), node(:child), node(:subchild)]
131
+ end
132
+
133
+ describe '.ancestor_of?' do
134
+ it "should return true for ancestors" do
135
+ node(:child).should be_ancestor_of(node(:subchild))
136
+ end
137
+
138
+ it "should return false for non-ancestors" do
139
+ node(:other_child).should_not be_ancestor_of(node(:subchild))
140
+ end
141
+ end
142
+ end
143
+
144
+ describe 'descendants' do
145
+ it ".descendants should return the documents descendants" do
146
+ node(:root).descendants.to_a.should =~ [node(:child), node(:other_child), node(:subchild)]
147
+ end
148
+
149
+ it ".descendants_and_self should return the documents descendants and itself" do
150
+ node(:root).descendants_and_self.to_a.should =~ [node(:root), node(:child), node(:other_child), node(:subchild)]
151
+ end
152
+
153
+ describe '.descendant_of?' do
154
+ it "should return true for descendants" do
155
+ subchild = node(:subchild)
156
+ subchild.should be_descendant_of(node(:child))
157
+ subchild.should be_descendant_of(node(:root))
158
+ end
159
+
160
+ it "should return false for non-descendants" do
161
+ node(:subchild).should_not be_descendant_of(node(:other_child))
162
+ end
163
+ end
164
+ end
165
+
166
+ describe 'siblings' do
167
+ it ".siblings should return the documents siblings" do
168
+ node(:child).siblings.to_a.should == [node(:other_child)]
169
+ end
170
+
171
+ it ".siblings_and_self should return the documents siblings and itself" do
172
+ node(:child).siblings_and_self.to_a.should == [node(:child), node(:other_child)]
173
+ end
174
+ end
175
+
176
+ end
177
+
178
+ end
@@ -0,0 +1,21 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ require 'mongoid'
5
+ require 'mongoid/tree'
6
+
7
+ require 'rspec'
8
+
9
+ Mongoid.configure do |config|
10
+ config.master = Mongo::Connection.new.db('mongoid_tree_test')
11
+ config.allow_dynamic_fields = false
12
+ end
13
+
14
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
15
+
16
+ RSpec.configure do |config|
17
+ config.mock_with :rspec
18
+ config.after :each do
19
+ Mongoid.master.collections.reject { |c| c.name =~ /^system\./ }.each(&:drop)
20
+ end
21
+ end
@@ -0,0 +1,46 @@
1
+ require 'yaml'
2
+
3
+ module Mongoid::Tree::TreeMacros
4
+
5
+ def setup_tree(tree)
6
+ create_tree(YAML.load(tree))
7
+ end
8
+
9
+ def node(name)
10
+ @nodes[name].reload
11
+ end
12
+
13
+ def print_tree(node, print_ids = false, depth = 0)
14
+ print ' ' * depth
15
+ print '- ' unless depth == 0
16
+ print node.name
17
+ print " (#{node.id})" if print_ids
18
+ print ':' if node.children.any?
19
+ print "\n"
20
+ node.children.each { |c| print_tree(c, print_ids, depth + 1) }
21
+ end
22
+
23
+ private
24
+
25
+ def create_tree(object)
26
+ case object
27
+ when String: return create_node(object)
28
+ when Array: object.each { |tree| create_tree(tree) }
29
+ when Hash:
30
+ name, children = object.first
31
+ node = create_node(name)
32
+ children.each { |c| node.children << create_tree(c) }
33
+ return node
34
+ end
35
+ end
36
+
37
+ def create_node(name)
38
+ @nodes ||= HashWithIndifferentAccess.new
39
+ @nodes[name] = Node.create(:name => name)
40
+ end
41
+
42
+ end
43
+
44
+ RSpec.configure do |config|
45
+ config.include Mongoid::Tree::TreeMacros
46
+ end
@@ -0,0 +1,7 @@
1
+ class Node
2
+ include Mongoid::Document
3
+ include Mongoid::Tree
4
+
5
+ field :name
6
+ end
7
+
metadata ADDED
@@ -0,0 +1,148 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mongoid-tree
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Benedikt Deicke
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-07-26 00:00:00 +02:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: mongoid
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: -1848230043
30
+ segments:
31
+ - 2
32
+ - 0
33
+ - 0
34
+ - beta9
35
+ version: 2.0.0.beta9
36
+ type: :runtime
37
+ version_requirements: *id001
38
+ - !ruby/object:Gem::Dependency
39
+ name: rspec
40
+ prerelease: false
41
+ requirement: &id002 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ hash: 62196423
47
+ segments:
48
+ - 2
49
+ - 0
50
+ - 0
51
+ - beta
52
+ - 18
53
+ version: 2.0.0.beta.18
54
+ type: :development
55
+ version_requirements: *id002
56
+ - !ruby/object:Gem::Dependency
57
+ name: autotest
58
+ prerelease: false
59
+ requirement: &id003 !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ hash: 55
65
+ segments:
66
+ - 4
67
+ - 3
68
+ - 2
69
+ version: 4.3.2
70
+ type: :development
71
+ version_requirements: *id003
72
+ - !ruby/object:Gem::Dependency
73
+ name: hanna
74
+ prerelease: false
75
+ requirement: &id004 !ruby/object:Gem::Requirement
76
+ none: false
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ hash: 3
81
+ segments:
82
+ - 0
83
+ - 1
84
+ - 12
85
+ version: 0.1.12
86
+ type: :development
87
+ version_requirements: *id004
88
+ description: A tree structure for Mongoid documents using the materialized path pattern
89
+ email:
90
+ - benedikt@synatic.net
91
+ executables: []
92
+
93
+ extensions: []
94
+
95
+ extra_rdoc_files:
96
+ - README.rdoc
97
+ - LICENSE
98
+ files:
99
+ - lib/mongoid/tree/traversal.rb
100
+ - lib/mongoid/tree.rb
101
+ - spec/mongoid/tree/traversal_spec.rb
102
+ - spec/mongoid/tree_spec.rb
103
+ - spec/spec_helper.rb
104
+ - spec/support/macros/tree_macros.rb
105
+ - spec/support/models/node.rb
106
+ - LICENSE
107
+ - README.rdoc
108
+ - Rakefile
109
+ - Gemfile
110
+ - .rspec
111
+ has_rdoc: true
112
+ homepage: http://github.com/benedikt/mongoid-tree
113
+ licenses: []
114
+
115
+ post_install_message:
116
+ rdoc_options:
117
+ - --main
118
+ - README.rdoc
119
+ - --charset=UTF-8
120
+ require_paths:
121
+ - lib
122
+ required_ruby_version: !ruby/object:Gem::Requirement
123
+ none: false
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ hash: 3
128
+ segments:
129
+ - 0
130
+ version: "0"
131
+ required_rubygems_version: !ruby/object:Gem::Requirement
132
+ none: false
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ hash: 3
137
+ segments:
138
+ - 0
139
+ version: "0"
140
+ requirements: []
141
+
142
+ rubyforge_project:
143
+ rubygems_version: 1.3.7
144
+ signing_key:
145
+ specification_version: 3
146
+ summary: A tree structure for Mongoid documents
147
+ test_files: []
148
+