mongoid-tree 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.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
+