mongoid-ancestry 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,5 +1,3 @@
1
- log/**
2
-
3
1
  # rcov generated
4
2
  coverage
5
3
 
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ rvm:
2
+ - 1.9.2
3
+ - 1.9.3
data/Gemfile CHANGED
@@ -3,5 +3,6 @@ source :rubygems
3
3
  gemspec
4
4
 
5
5
  group :test do
6
+ gem 'rake'
6
7
  gem 'rspec', '~> 2.5'
7
8
  end
data/Gemfile.lock CHANGED
@@ -1,30 +1,33 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mongoid-ancestry (0.2.2)
5
- bson_ext (~> 1.3)
6
- mongoid (~> 2.0)
4
+ mongoid-ancestry (0.2.3)
5
+ bson_ext (>= 1.3)
6
+ mongoid (>= 2.0)
7
7
 
8
8
  GEM
9
9
  remote: http://rubygems.org/
10
10
  specs:
11
- activemodel (3.0.7)
12
- activesupport (= 3.0.7)
13
- builder (~> 2.1.2)
14
- i18n (~> 0.5.0)
15
- activesupport (3.0.7)
16
- bson (1.3.0)
17
- bson_ext (1.3.0)
18
- builder (2.1.2)
11
+ activemodel (3.2.5)
12
+ activesupport (= 3.2.5)
13
+ builder (~> 3.0.0)
14
+ activesupport (3.2.5)
15
+ i18n (~> 0.6)
16
+ multi_json (~> 1.0)
17
+ bson (1.6.4)
18
+ bson_ext (1.6.4)
19
+ bson (~> 1.6.4)
20
+ builder (3.0.0)
19
21
  diff-lcs (1.1.2)
20
- i18n (0.5.0)
21
- mongo (1.3.0)
22
- bson (>= 1.3.0)
23
- mongoid (2.0.1)
24
- activemodel (~> 3.0)
22
+ i18n (0.6.0)
23
+ mongo (1.6.2)
24
+ bson (~> 1.6.2)
25
+ mongoid (2.4.7)
26
+ activemodel (~> 3.1)
25
27
  mongo (~> 1.3)
26
28
  tzinfo (~> 0.3.22)
27
- will_paginate (~> 3.0.pre)
29
+ multi_json (1.3.6)
30
+ rake (0.9.2.2)
28
31
  rspec (2.5.0)
29
32
  rspec-core (~> 2.5.0)
30
33
  rspec-expectations (~> 2.5.0)
@@ -33,12 +36,12 @@ GEM
33
36
  rspec-expectations (2.5.0)
34
37
  diff-lcs (~> 1.1.2)
35
38
  rspec-mocks (2.5.0)
36
- tzinfo (0.3.26)
37
- will_paginate (3.0.pre2)
39
+ tzinfo (0.3.33)
38
40
 
39
41
  PLATFORMS
40
42
  ruby
41
43
 
42
44
  DEPENDENCIES
43
45
  mongoid-ancestry!
46
+ rake
44
47
  rspec (~> 2.5)
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  Mongoid-ancestry
2
2
  ================
3
3
 
4
+ [![travis](https://secure.travis-ci.org/joe1chen/mongoid-ancestry.png)](http://travis-ci.org/joe1chen/mongoid-ancestry)
5
+
4
6
  Mongoid-ancestry is a gem/plugin that allows the records of a Ruby on Rails Mongoid model to be organised as a tree structure (or hierarchy). It uses a single, intuitively formatted database column, using a variation on the materialised path pattern. It exposes all the standard tree structure relations (ancestors, parent, root, children, siblings, descendants) and all of them can be fetched in a single query. Additional features are STI support, scopes, depth caching, depth constraints, easy migration from older plugins/gems, integrity checking, integrity restoration, arrangement of (sub)tree into hashes and different strategies for dealing with orphaned records.
5
7
 
6
8
  ## Installation
@@ -23,9 +25,9 @@ Your model is now a tree!
23
25
 
24
26
  ## Organising records into a tree
25
27
  You can use the parent attribute to organise your records into a tree. If you have the id of the record you want
26
- to use as a parent and don't want to fetch it, you can also use parent_id. Like any virtual model attributes,
27
- parent and parent_id can be set using parent= and parent_id= on a record or by including them in the hash passed
28
- to new, create, create!, update_attributes and update_attributes!. For example:
28
+ to use as a parent and don't want to fetch it, you can also use `parent_id`. Like any virtual model attributes,
29
+ parent and `parent_id` can be set using `parent=` and `parent_id=` on a record or by including them in the hash passed
30
+ to new, create, create!, `update_attributes` and `update_attributes!`. For example:
29
31
 
30
32
  TreeNode.create :name => 'Stinky', :parent => TreeNode.create(:name => 'Squeeky')
31
33
 
@@ -69,15 +71,18 @@ To navigate an Ancestry model, use the following methods on any instance / recor
69
71
 
70
72
  ## Options for has_ancestry
71
73
 
72
- The has_ancestry methods supports the following options:
74
+ The `has_ancestry` methods supports the following options:
73
75
 
74
76
  :ancestry_field Pass in a symbol to store ancestry in a different field
75
77
  :orphan_strategy Instruct Ancestry what to do with children of a node that is destroyed:
76
78
  :destroy All children are destroyed as well (default)
77
79
  :rootify The children of the destroyed node become root nodes
78
80
  :restrict An Error is raised if any children exist
79
- :cache_depth Cache the depth of each node in the 'ancestry_depth' field (default: false)
81
+ :cache_depth Cache the depth of each node in the `ancestry_depth` field (default: false)
80
82
  If you turn depth_caching on for an existing model:
83
+ - Mongoid has default configuration attribute `allow_dynamic_fields` as `true`.
84
+ You should manually add this depth field with `Integer` type and `0` as default value
85
+ into your model if `allow_dynamic_fields` is disabled in your configuration.
81
86
  - Build cache: TreeNode.rebuild_depth_cache!
82
87
  :depth_cache_field Pass in a symbol to store depth cache in a different field
83
88
 
@@ -107,7 +112,7 @@ Thanks to some convenient rails magic, it is even possible to create nodes throu
107
112
 
108
113
  ## Selecting nodes by depth
109
114
 
110
- When depth caching is enabled (see has_ancestry options), five more named scopes can be used to select nodes on their depth:
115
+ When depth caching is enabled (see `has_ancestry` options), five more named scopes can be used to select nodes on their depth:
111
116
 
112
117
  before_depth(depth) Return nodes that are less deep than depth (node.depth < depth)
113
118
  to_depth(depth) Return nodes up to a certain depth (node.depth <= depth)
@@ -115,7 +120,7 @@ When depth caching is enabled (see has_ancestry options), five more named scopes
115
120
  from_depth(depth) Return nodes starting from a certain depth (node.depth >= depth)
116
121
  after_depth(depth) Return nodes that are deeper than depth (node.depth > depth)
117
122
 
118
- The depth scopes are also available through calls to descendants, descendant_ids, subtree, subtree_ids, path and ancestors. In this case, depth values are interpreted relatively. Some examples:
123
+ The depth scopes are also available through calls to `descendants`, `descendant_ids`, `subtree`, `subtree_ids`, `path` and `ancestors`. In this case, depth values are interpreted relatively. Some examples:
119
124
 
120
125
  node.subtree(:to_depth => 2) Subtree of node, to a depth of node.depth + 2 (self, children and grandchildren)
121
126
  node.subtree.to_depth(5) Subtree of node to an absolute depth of 5
@@ -129,7 +134,10 @@ The depth scopes are also available through calls to descendants, descendant_ids
129
134
  node.descendants(:from_depth => 2, :to_depth => 4)
130
135
  node.subtree.from_depth(10).to_depth(12)
131
136
 
132
- Please note that depth constraints cannot be passed to ancestor_ids and path_ids. The reason for this is that both these relations can be fetched directly from the ancestry column without performing a database query. It would require an entirely different method of applying the depth constraints which isn't worth the effort of implementing. You can use ancestors(depth_options).map(&:id) or ancestor_ids.slice(min_depth..max_depth) instead.
137
+ Please note that depth constraints cannot be passed to `ancestor_ids` and `path_ids`. The reason for this is that
138
+ both these relations can be fetched directly from the ancestry column without performing a database query. It would
139
+ require an entirely different method of applying the depth constraints which isn't worth the effort of implementing.
140
+ You can use `ancestors(depth_options).map(&:id)` or `ancestor_ids.slice(min_depth..max_depth)` instead.
133
141
 
134
142
  ## STI support
135
143
 
@@ -157,11 +165,11 @@ The arrange method takes Mongoid find options. If you want your hashes to be ord
157
165
 
158
166
  ## Migrating from plugin that uses parent_id column
159
167
 
160
- With Mongoid-ancestry its easy to migrate from any of these plugins, to do so, use the build_ancestry_from_parent_ids! method on your model. These steps provide a more detailed explanation:
168
+ With Mongoid-ancestry its easy to migrate from any of these plugins, to do so, use the `Model.build_ancestry_from_parent_ids!` method on your model. These steps provide a more detailed explanation:
161
169
 
162
170
  1. Remove old tree plugin or gem and add in Mongoid-ancestry
163
171
  * See 'Installation' for more info on installing and configuring gem
164
- * Add to app/models/[model].rb:
172
+ * Add to app/models/model.rb:
165
173
 
166
174
  include Mongoid::Ancestry
167
175
  has_ancestry
@@ -173,13 +181,13 @@ Most tree calls will probably work fine with ancestry
173
181
  Others must be changed or proxied
174
182
  Check if all your data is intact and all tests pass
175
183
 
176
- 3. Drop parent_id field
184
+ 3. Drop `parent_id` field
177
185
 
178
186
  ## Integrity checking and restoration
179
187
 
180
- I don't see any way Mongoid-ancestry tree integrity could get compromised without explicitly setting cyclic parents or invalid ancestry and circumventing validation with update_attribute, if you do, please let me know.
188
+ I don't see any way Mongoid-ancestry tree integrity could get compromised without explicitly setting cyclic parents or invalid ancestry and circumventing validation with `update_attribute`, if you do, please let me know.
181
189
 
182
- Mongoid-ancestry includes some methods for detecting integrity problems and restoring integrity just to be sure. To check integrity use: [Model].check_ancestry_integrity!. An Mongoid::Ancestry::Error will be raised if there are any problems. You can also specify :report => :list to return an array of exceptions or :report => :echo to echo any error messages. To restore integrity use: [Model].restore_ancestry_integrity!.
190
+ Mongoid-ancestry includes some methods for detecting integrity problems and restoring integrity just to be sure. To check integrity use: `Model.check_ancestry_integrity!`. An Mongoid::Ancestry::Error will be raised if there are any problems. You can also specify `:report => :list` to return an array of exceptions or `:report => :echo` to echo any error messages. To restore integrity use: `Model.restore_ancestry_integrity!`.
183
191
 
184
192
  For example, from IRB:
185
193
 
@@ -202,13 +210,13 @@ Additionally, if you think something is wrong with your depth cache:
202
210
 
203
211
  ## Tests
204
212
 
205
- The Mongoid-ancestry gem comes with rspec and guard(for automatically specs running) suite consisting of about 40 specs. It takes about 10 seconds to run. To run it yourself check out the repository from GitHub, run `bundle install`, run `guard` and press `Ctrl+\` or just `rake spec`.
213
+ The Mongoid-ancestry gem comes with rspec and guard(for automatically specs running) suite consisting of about 40 specs. It takes about 10 seconds to run. To run it yourself check out the repository from GitHub, run `bundle install`, run `guard` and press `Ctrl+\ ` or just `rake spec`.
206
214
 
207
215
  ## Internals
208
216
 
209
217
  As can be seen in the previous section, Mongoid-ancestry stores a path from the root to the parent for every node. This is a variation on the materialised path database pattern. It allows to fetch any relation (siblings, descendants, etc.) in a single query without the complicated algorithms and incomprehensibility associated with left and right values. Additionally, any inserts, deletes and updates only affect nodes within the affected node's own subtree.
210
218
 
211
- The materialised path pattern requires Mongoid-ancestry to use a 'regexp' condition in order to fetch descendants. This should not be particularly slow however since the the condition never starts with a wildcard which allows the DBMS to use the column index. If you have any data on performance with a large number of records, please drop me line.
219
+ The materialised path pattern requires Mongoid-ancestry to use a `regexp` condition in order to fetch descendants. This should not be particularly slow however since the the condition never starts with a wildcard which allows the DBMS to use the column index. If you have any data on performance with a large number of records, please drop me line.
212
220
 
213
221
  ## Contact and copyright
214
222
 
data/Rakefile CHANGED
@@ -10,7 +10,7 @@ end
10
10
 
11
11
  task :default => :spec
12
12
 
13
- require 'rake/rdoctask'
13
+ require 'rdoc/task'
14
14
  Rake::RDocTask.new do |rdoc|
15
15
  version = File.exist?('VERSION') ? File.read('VERSION') : ""
16
16
 
@@ -1,243 +1,243 @@
1
1
  module Mongoid
2
2
  module Ancestry
3
- module InstanceMethods
4
- # Validate that the ancestors don't include itself
5
- def ancestry_exclude_self
6
- if ancestor_ids.include? id
7
- errors.add(:base, "#{self.class.name.humanize} cannot be a descendant of itself.")
8
- end
3
+
4
+ # Validate that the ancestors don't include itself
5
+ def ancestry_exclude_self
6
+ if ancestor_ids.include? id
7
+ errors.add(:base, "#{self.class.name.humanize} cannot be a descendant of itself.")
9
8
  end
9
+ end
10
10
 
11
- # Update descendants with new ancestry
12
- def update_descendants_with_new_ancestry
13
- # Skip this if callbacks are disabled
14
- unless ancestry_callbacks_disabled?
15
- # If node is valid, not a new record and ancestry was updated ...
16
- if changed.include?(self.base_class.ancestry_field.to_s) && !new_record? && valid?
17
- # ... for each descendant ...
18
- descendants.each do |descendant|
19
- # ... replace old ancestry with new ancestry
20
- descendant.without_ancestry_callbacks do
21
- for_replace = \
22
- if read_attribute(self.class.ancestry_field).blank?
23
- id.to_s
24
- else
25
- "#{read_attribute self.class.ancestry_field}/#{id}"
26
- end
27
- new_ancestry = descendant.read_attribute(descendant.class.ancestry_field).gsub(/^#{self.child_ancestry}/, for_replace)
28
- descendant.update_attribute(self.base_class.ancestry_field, new_ancestry)
29
- end
11
+ # Update descendants with new ancestry
12
+ def update_descendants_with_new_ancestry
13
+ # Skip this if callbacks are disabled
14
+ unless ancestry_callbacks_disabled?
15
+ # If node is valid, not a new record and ancestry was updated ...
16
+ if changed.include?(self.base_class.ancestry_field.to_s) && !new_record? && valid?
17
+ # ... for each descendant ...
18
+ descendants.each do |descendant|
19
+ # ... replace old ancestry with new ancestry
20
+ descendant.without_ancestry_callbacks do
21
+ for_replace = \
22
+ if read_attribute(self.class.ancestry_field).blank?
23
+ id.to_s
24
+ else
25
+ "#{read_attribute self.class.ancestry_field}/#{id}"
26
+ end
27
+ new_ancestry = descendant.read_attribute(descendant.class.ancestry_field).gsub(/^#{self.child_ancestry}/, for_replace)
28
+ descendant.update_attribute(self.base_class.ancestry_field, new_ancestry)
30
29
  end
31
30
  end
32
31
  end
33
32
  end
33
+ end
34
34
 
35
- # Apply orphan strategy
36
- def apply_orphan_strategy
37
- # Skip this if callbacks are disabled
38
- unless ancestry_callbacks_disabled?
39
- # If this isn't a new record ...
40
- unless new_record?
41
- # ... make al children root if orphan strategy is rootify
42
- if self.base_class.orphan_strategy == :rootify
43
- descendants.each do |descendant|
44
- descendant.without_ancestry_callbacks do
45
- val = \
46
- unless descendant.ancestry == child_ancestry
47
- descendant.read_attribute(descendant.class.ancestry_field).gsub(/^#{child_ancestry}\//, '')
48
- end
49
- descendant.update_attribute descendant.class.ancestry_field, val
50
- end
51
- end
52
- # ... destroy all descendants if orphan strategy is destroy
53
- elsif self.base_class.orphan_strategy == :destroy
54
- descendants.all.each do |descendant|
55
- descendant.without_ancestry_callbacks { descendant.destroy }
35
+ # Apply orphan strategy
36
+ def apply_orphan_strategy
37
+ # Skip this if callbacks are disabled
38
+ unless ancestry_callbacks_disabled?
39
+ # If this isn't a new record ...
40
+ unless new_record?
41
+ # ... make al children root if orphan strategy is rootify
42
+ if self.base_class.orphan_strategy == :rootify
43
+ descendants.each do |descendant|
44
+ descendant.without_ancestry_callbacks do
45
+ val = \
46
+ unless descendant.ancestry == child_ancestry
47
+ descendant.read_attribute(descendant.class.ancestry_field).gsub(/^#{child_ancestry}\//, '')
48
+ end
49
+ descendant.update_attribute descendant.class.ancestry_field, val
56
50
  end
57
- # ... throw an exception if it has children and orphan strategy is restrict
58
- elsif self.base_class.orphan_strategy == :restrict
59
- raise Error.new('Cannot delete record because it has descendants.') unless is_childless?
60
51
  end
52
+ # ... destroy all descendants if orphan strategy is destroy
53
+ elsif self.base_class.orphan_strategy == :destroy
54
+ descendants.all.each do |descendant|
55
+ descendant.without_ancestry_callbacks { descendant.destroy }
56
+ end
57
+ # ... throw an exception if it has children and orphan strategy is restrict
58
+ elsif self.base_class.orphan_strategy == :restrict
59
+ raise Error.new('Cannot delete record because it has descendants.') unless is_childless?
61
60
  end
62
61
  end
63
62
  end
63
+ end
64
64
 
65
- # The ancestry value for this record's children
66
- def child_ancestry
67
- # New records cannot have children
68
- raise Error.new('No child ancestry for new record. Save record before performing tree operations.') if new_record?
65
+ # The ancestry value for this record's children
66
+ def child_ancestry
67
+ # New records cannot have children
68
+ raise Error.new('No child ancestry for new record. Save record before performing tree operations.') if new_record?
69
69
 
70
- if self.send("#{self.base_class.ancestry_field}_was").blank?
71
- id.to_s
72
- else
73
- "#{self.send "#{self.base_class.ancestry_field}_was"}/#{id}"
74
- end
70
+ if self.send("#{self.base_class.ancestry_field}_was").blank?
71
+ id.to_s
72
+ else
73
+ "#{self.send "#{self.base_class.ancestry_field}_was"}/#{id}"
75
74
  end
75
+ end
76
76
 
77
- # Ancestors
78
- def ancestor_ids
79
- read_attribute(self.base_class.ancestry_field).to_s.split('/').map { |id| cast_primary_key(id) }
80
- end
77
+ # Ancestors
78
+ def ancestor_ids
79
+ read_attribute(self.base_class.ancestry_field).to_s.split('/').map { |id| cast_primary_key(id) }
80
+ end
81
81
 
82
- def ancestor_conditions
83
- { :_id.in => ancestor_ids }
84
- end
82
+ def ancestor_conditions
83
+ { :_id.in => ancestor_ids }
84
+ end
85
85
 
86
- def ancestors depth_options = {}
87
- self.base_class.scope_depth(depth_options, depth).where(ancestor_conditions)
88
- end
86
+ def ancestors depth_options = {}
87
+ self.base_class.scope_depth(depth_options, depth).where(ancestor_conditions)
88
+ end
89
89
 
90
- def path_ids
91
- ancestor_ids + [id]
92
- end
90
+ def path_ids
91
+ ancestor_ids + [id]
92
+ end
93
93
 
94
- def path_conditions
95
- { :_id.in => path_ids }
96
- end
94
+ def path_conditions
95
+ { :_id.in => path_ids }
96
+ end
97
97
 
98
- def path depth_options = {}
99
- self.base_class.scope_depth(depth_options, depth).where(path_conditions)
100
- end
98
+ def path depth_options = {}
99
+ self.base_class.scope_depth(depth_options, depth).where(path_conditions)
100
+ end
101
101
 
102
- def depth
103
- ancestor_ids.size
104
- end
102
+ def depth
103
+ ancestor_ids.size
104
+ end
105
105
 
106
- def cache_depth
107
- write_attribute self.base_class.depth_cache_field, depth
108
- end
106
+ def cache_depth
107
+ write_attribute self.base_class.depth_cache_field, depth
108
+ end
109
109
 
110
- # Parent
111
- def parent= parent
112
- write_attribute(self.base_class.ancestry_field, parent.blank? ? nil : parent.child_ancestry)
113
- end
110
+ # Parent
111
+ def parent= parent
112
+ write_attribute(self.base_class.ancestry_field, parent.blank? ? nil : parent.child_ancestry)
113
+ end
114
114
 
115
- def parent_id= parent_id
116
- self.parent = parent_id.blank? ? nil : self.base_class.find(parent_id)
117
- end
115
+ def parent_id= parent_id
116
+ self.parent = parent_id.blank? ? nil : self.base_class.find(parent_id)
117
+ end
118
118
 
119
- def parent_id
120
- ancestor_ids.empty? ? nil : ancestor_ids.last
121
- end
119
+ def parent_id
120
+ ancestor_ids.empty? ? nil : ancestor_ids.last
121
+ end
122
122
 
123
- def parent
124
- parent_id.blank? ? nil : self.base_class.find(parent_id)
125
- end
123
+ def parent
124
+ parent_id.blank? ? nil : self.base_class.find(parent_id)
125
+ end
126
126
 
127
- # Root
128
- def root_id
129
- ancestor_ids.empty? ? id : ancestor_ids.first
130
- end
127
+ # Root
128
+ def root_id
129
+ ancestor_ids.empty? ? id : ancestor_ids.first
130
+ end
131
131
 
132
- def root
133
- (root_id == id) ? self : self.base_class.find(root_id)
134
- end
132
+ def root
133
+ (root_id == id) ? self : self.base_class.find(root_id)
134
+ end
135
135
 
136
- def is_root?
137
- read_attribute(self.base_class.ancestry_field).blank?
138
- end
136
+ def is_root?
137
+ read_attribute(self.base_class.ancestry_field).blank?
138
+ end
139
139
 
140
- # Children
141
- def child_conditions
142
- {self.base_class.ancestry_field => child_ancestry}
143
- end
140
+ # Children
141
+ def child_conditions
142
+ {self.base_class.ancestry_field => child_ancestry}
143
+ end
144
144
 
145
- def children
146
- self.base_class.where(child_conditions)
147
- end
145
+ def children
146
+ self.base_class.where(child_conditions)
147
+ end
148
148
 
149
- def child_ids
150
- children.only(:_id).map(&:id)
151
- end
149
+ def child_ids
150
+ children.only(:_id).map(&:id)
151
+ end
152
152
 
153
- def has_children?
154
- self.children.present?
155
- end
153
+ def has_children?
154
+ self.children.present?
155
+ end
156
156
 
157
- def is_childless?
158
- !has_children?
159
- end
157
+ def is_childless?
158
+ !has_children?
159
+ end
160
160
 
161
- # Siblings
162
- def sibling_conditions
163
- {self.base_class.ancestry_field => read_attribute(self.base_class.ancestry_field)}
164
- end
161
+ # Siblings
162
+ def sibling_conditions
163
+ {self.base_class.ancestry_field => read_attribute(self.base_class.ancestry_field)}
164
+ end
165
165
 
166
- def siblings
167
- self.base_class.where sibling_conditions
168
- end
166
+ def siblings
167
+ self.base_class.where sibling_conditions
168
+ end
169
169
 
170
- def sibling_ids
171
- siblings.only(:_id).map(&:id)
172
- end
170
+ def sibling_ids
171
+ siblings.only(:_id).map(&:id)
172
+ end
173
173
 
174
- def has_siblings?
175
- self.siblings.count > 1
176
- end
174
+ def has_siblings?
175
+ self.siblings.count > 1
176
+ end
177
177
 
178
- def is_only_child?
179
- !has_siblings?
180
- end
178
+ def is_only_child?
179
+ !has_siblings?
180
+ end
181
181
 
182
- # Descendants
183
- def descendant_conditions
184
- [
185
- { self.base_class.ancestry_field => /^#{child_ancestry}\// },
186
- { self.base_class.ancestry_field => child_ancestry }
187
- ]
188
- end
182
+ # Descendants
183
+ def descendant_conditions
184
+ [
185
+ { self.base_class.ancestry_field => /^#{child_ancestry}\// },
186
+ { self.base_class.ancestry_field => child_ancestry }
187
+ ]
188
+ end
189
189
 
190
- def descendants depth_options = {}
191
- self.base_class.scope_depth(depth_options, depth).any_of(descendant_conditions)
192
- end
190
+ def descendants depth_options = {}
191
+ self.base_class.scope_depth(depth_options, depth).any_of(descendant_conditions)
192
+ end
193
193
 
194
- def descendant_ids depth_options = {}
195
- descendants(depth_options).only(:_id).map(&:id)
196
- end
194
+ def descendant_ids depth_options = {}
195
+ descendants(depth_options).only(:_id).map(&:id)
196
+ end
197
197
 
198
- # Subtree
199
- def subtree_conditions
200
- [
201
- { :_id => id },
202
- { self.base_class.ancestry_field => /^#{child_ancestry}\// },
203
- { self.base_class.ancestry_field => child_ancestry }
204
- ]
205
- end
198
+ # Subtree
199
+ def subtree_conditions
200
+ [
201
+ { :_id => id },
202
+ { self.base_class.ancestry_field => /^#{child_ancestry}\// },
203
+ { self.base_class.ancestry_field => child_ancestry }
204
+ ]
205
+ end
206
206
 
207
- def subtree depth_options = {}
208
- self.base_class.scope_depth(depth_options, depth).any_of(subtree_conditions)
209
- end
207
+ def subtree depth_options = {}
208
+ self.base_class.scope_depth(depth_options, depth).any_of(subtree_conditions)
209
+ end
210
210
 
211
- def subtree_ids depth_options = {}
212
- subtree(depth_options).only(:_id).map(&:id)
213
- end
211
+ def subtree_ids depth_options = {}
212
+ subtree(depth_options).only(:_id).map(&:id)
213
+ end
214
214
 
215
- # Callback disabling
216
- def without_ancestry_callbacks
217
- @disable_ancestry_callbacks = true
218
- yield
219
- @disable_ancestry_callbacks = false
220
- end
215
+ # Callback disabling
216
+ def without_ancestry_callbacks
217
+ @disable_ancestry_callbacks = true
218
+ yield
219
+ @disable_ancestry_callbacks = false
220
+ end
221
221
 
222
- def ancestry_callbacks_disabled?
223
- !!@disable_ancestry_callbacks
224
- end
222
+ def ancestry_callbacks_disabled?
223
+ !!@disable_ancestry_callbacks
224
+ end
225
225
 
226
- private
226
+ private
227
227
 
228
- def cast_primary_key(key)
229
- if primary_key_type == Integer
230
- key.to_i
231
- elsif primary_key_type == BSON::ObjectId && key =~ /[a-z0-9]{24}/
232
- BSON::ObjectId.convert(self, key)
233
- else
234
- key
235
- end
228
+ def cast_primary_key(key)
229
+ if primary_key_type == Integer
230
+ key.to_i
231
+ elsif primary_key_type == BSON::ObjectId && key =~ /[a-z0-9]{24}/
232
+ BSON::ObjectId.convert(self, key)
233
+ else
234
+ key
236
235
  end
236
+ end
237
237
 
238
- def primary_key_type
239
- @primary_key_type ||= self.base_class.fields['_id'].options[:type]
240
- end
238
+ def primary_key_type
239
+ @primary_key_type ||= self.base_class.fields['_id'].options[:type]
241
240
  end
242
241
  end
242
+
243
243
  end
@@ -1,5 +1,5 @@
1
1
  module Mongoid
2
2
  module Ancestry
3
- VERSION = '0.2.2'
3
+ VERSION = '0.2.3'
4
4
  end
5
5
  end
@@ -3,12 +3,13 @@ module Mongoid
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  autoload :ClassMethods, 'mongoid-ancestry/class_methods'
6
- autoload :InstanceMethods, 'mongoid-ancestry/instance_methods'
7
6
  autoload :Error, 'mongoid-ancestry/exceptions'
8
7
 
9
8
  included do
10
9
  cattr_accessor :base_class
11
10
  self.base_class = self
12
11
  end
12
+
13
+ require 'mongoid-ancestry/instance_methods'
13
14
  end
14
15
  end
data/log/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ # Ignore everything in this directory
2
+ *
3
+ # Except this file
4
+ !.gitignore
@@ -23,7 +23,7 @@ Gem::Specification.new do |s|
23
23
  "README.md"
24
24
  ]
25
25
 
26
- s.add_dependency('mongoid', "~> 2.0")
27
- s.add_dependency('bson_ext', "~> 1.3")
26
+ s.add_dependency('mongoid', ">= 2.0")
27
+ s.add_dependency('bson_ext', ">= 1.3")
28
28
  end
29
29
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid-ancestry
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,31 +10,40 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2011-04-26 00:00:00.000000000 +04:00
14
- default_executable:
13
+ date: 2012-06-25 00:00:00.000000000 Z
15
14
  dependencies:
16
15
  - !ruby/object:Gem::Dependency
17
16
  name: mongoid
18
- requirement: &19610840 !ruby/object:Gem::Requirement
17
+ requirement: !ruby/object:Gem::Requirement
19
18
  none: false
20
19
  requirements:
21
- - - ~>
20
+ - - ! '>='
22
21
  - !ruby/object:Gem::Version
23
22
  version: '2.0'
24
23
  type: :runtime
25
24
  prerelease: false
26
- version_requirements: *19610840
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: '2.0'
27
31
  - !ruby/object:Gem::Dependency
28
32
  name: bson_ext
29
- requirement: &19610240 !ruby/object:Gem::Requirement
33
+ requirement: !ruby/object:Gem::Requirement
30
34
  none: false
31
35
  requirements:
32
- - - ~>
36
+ - - ! '>='
33
37
  - !ruby/object:Gem::Version
34
38
  version: '1.3'
35
39
  type: :runtime
36
40
  prerelease: false
37
- version_requirements: *19610240
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '1.3'
38
47
  description: Organise Mongoid model into a tree structure
39
48
  email:
40
49
  - eagle.anton@gmail.com
@@ -44,6 +53,7 @@ extra_rdoc_files:
44
53
  - README.md
45
54
  files:
46
55
  - .gitignore
56
+ - .travis.yml
47
57
  - Gemfile
48
58
  - Gemfile.lock
49
59
  - Guardfile
@@ -57,13 +67,13 @@ files:
57
67
  - lib/mongoid-ancestry/exceptions.rb
58
68
  - lib/mongoid-ancestry/instance_methods.rb
59
69
  - lib/mongoid-ancestry/version.rb
70
+ - log/.gitignore
60
71
  - mongoid-ancestry.gemspec
61
72
  - spec/lib/ancestry_spec.rb
62
73
  - spec/lib/mongoid-ancestry/class_methods_spec.rb
63
74
  - spec/lib/mongoid-ancestry/instance_methods_spec.rb
64
75
  - spec/spec_helper.rb
65
76
  - spec/support/models.rb
66
- has_rdoc: true
67
77
  homepage: http://github.com/skyeagle/mongoid-ancestry
68
78
  licenses:
69
79
  - MIT
@@ -79,7 +89,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
79
89
  version: '0'
80
90
  segments:
81
91
  - 0
82
- hash: 582045907932447253
92
+ hash: -4473599239750644479
83
93
  required_rubygems_version: !ruby/object:Gem::Requirement
84
94
  none: false
85
95
  requirements:
@@ -88,10 +98,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
88
98
  version: '0'
89
99
  segments:
90
100
  - 0
91
- hash: 582045907932447253
101
+ hash: -4473599239750644479
92
102
  requirements: []
93
103
  rubyforge_project: mongoid-ancestry
94
- rubygems_version: 1.5.2
104
+ rubygems_version: 1.8.24
95
105
  signing_key:
96
106
  specification_version: 3
97
107
  summary: Ancestry allows the records of a Mongoid model to be organised in a tree