mongoid-ancestry-fixes 0.0.1 → 0.0.2
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.
- checksums.yaml +8 -8
- metadata +11 -34
- data/.gitignore +0 -42
- data/.travis.yml +0 -3
- data/Gemfile +0 -8
- data/Gemfile.lock +0 -47
- data/Guardfile +0 -10
- data/MIT-LICENSE +0 -20
- data/Rakefile +0 -21
- data/init.rb +0 -1
- data/install.rb +0 -1
- data/lib/mongoid-ancestry.rb +0 -15
- data/lib/mongoid-ancestry/class_methods.rb +0 -212
- data/lib/mongoid-ancestry/exceptions.rb +0 -6
- data/lib/mongoid-ancestry/instance_methods.rb +0 -248
- data/lib/mongoid-ancestry/version.rb +0 -5
- data/log/.gitignore +0 -4
- data/mongoid-ancestry.gemspec +0 -29
- data/spec/lib/ancestry_spec.rb +0 -110
- data/spec/lib/mongoid-ancestry/class_methods_spec.rb +0 -300
- data/spec/lib/mongoid-ancestry/instance_methods_spec.rb +0 -241
- data/spec/spec_helper.rb +0 -22
- data/spec/support/models.rb +0 -40
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ZmM5YTM5MDAwNjg4NmRhYzRlNzEzOTY4YmMzYjgzODhhMTMzYTJkMQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MjZiMWQ3MTU4NzZkNWExNmU4YTY4NzVkNzI0YzI4MzEwOWRiNjNiOQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NTdlNmUxYWFkZmNkMTU5ZjkxZWQ5MDM4ZTFkMzk5NDczYjE2NmFmZTJjMWUy
|
10
|
+
OWRiMWQxNzMwMGEwZWNiNGU1N2JhY2IyM2Q3NGNkY2EyMDI1NGVkNzcxMGI5
|
11
|
+
ZDEwZjlhMzgzY2MxNGI5NjZhMWM3YzNmNjhmYWE5MWVjMjJhNGM=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
YmRjNDQwMjIyMWUyYWM4OWJjZTdhN2VjNzc1YmU1ZDEzMGYwOWMwZjA3YTRi
|
14
|
+
NGFkNDUyOGQ1YTk2MzFkNGVmNzk4YTZkMDQ0YzI2MDQzNWUyMmNmNTFhODg2
|
15
|
+
ZDg0NTM1YTFkNGRmYjJhZTY0ZWJmNTAwY2UxZTdjNzQ3M2E4ZDI=
|
metadata
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongoid-ancestry-fixes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stefan Kroes
|
8
8
|
- Anton Orel
|
9
|
+
- fl00r
|
10
|
+
- shilovk
|
9
11
|
autorequire:
|
10
12
|
bindir: bin
|
11
13
|
cert_chain: []
|
@@ -47,28 +49,7 @@ extensions: []
|
|
47
49
|
extra_rdoc_files:
|
48
50
|
- README.md
|
49
51
|
files:
|
50
|
-
- .gitignore
|
51
|
-
- .travis.yml
|
52
|
-
- Gemfile
|
53
|
-
- Gemfile.lock
|
54
|
-
- Guardfile
|
55
|
-
- MIT-LICENSE
|
56
52
|
- README.md
|
57
|
-
- Rakefile
|
58
|
-
- init.rb
|
59
|
-
- install.rb
|
60
|
-
- lib/mongoid-ancestry.rb
|
61
|
-
- lib/mongoid-ancestry/class_methods.rb
|
62
|
-
- lib/mongoid-ancestry/exceptions.rb
|
63
|
-
- lib/mongoid-ancestry/instance_methods.rb
|
64
|
-
- lib/mongoid-ancestry/version.rb
|
65
|
-
- log/.gitignore
|
66
|
-
- mongoid-ancestry.gemspec
|
67
|
-
- spec/lib/ancestry_spec.rb
|
68
|
-
- spec/lib/mongoid-ancestry/class_methods_spec.rb
|
69
|
-
- spec/lib/mongoid-ancestry/instance_methods_spec.rb
|
70
|
-
- spec/spec_helper.rb
|
71
|
-
- spec/support/models.rb
|
72
53
|
homepage: http://github.com/skyeagle/mongoid-ancestry
|
73
54
|
licenses:
|
74
55
|
- MIT
|
@@ -92,15 +73,11 @@ rubyforge_project: mongoid-ancestry-fixes
|
|
92
73
|
rubygems_version: 2.4.5
|
93
74
|
signing_key:
|
94
75
|
specification_version: 4
|
95
|
-
summary:
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
- spec/lib/mongoid-ancestry/class_methods_spec.rb
|
104
|
-
- spec/lib/mongoid-ancestry/instance_methods_spec.rb
|
105
|
-
- spec/spec_helper.rb
|
106
|
-
- spec/support/models.rb
|
76
|
+
summary: This is a fork of mongoid-ancestry-0.2.3 with some fixes. Ancestry allows
|
77
|
+
the records of a Mongoid model to be organised in a tree structure, using a single,
|
78
|
+
intuitively formatted database field. It exposes all the standard tree structure
|
79
|
+
relations (ancestors, parent, root, children, siblings, descendants) and all of
|
80
|
+
them can be fetched in a single query. Additional features are named_scopes, integrity
|
81
|
+
checking, integrity restoration, arrangement of (sub)tree into hashes and different
|
82
|
+
strategies for dealing with orphaned records.
|
83
|
+
test_files: []
|
data/.gitignore
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
# rcov generated
|
2
|
-
coverage
|
3
|
-
|
4
|
-
# rdoc generated
|
5
|
-
rdoc
|
6
|
-
|
7
|
-
# yard generated
|
8
|
-
doc
|
9
|
-
.yardoc
|
10
|
-
|
11
|
-
# bundler
|
12
|
-
.bundle
|
13
|
-
|
14
|
-
# jeweler generated
|
15
|
-
pkg
|
16
|
-
|
17
|
-
# Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
|
18
|
-
#
|
19
|
-
# * Create a file at ~/.gitignore
|
20
|
-
# * Include files you want ignored
|
21
|
-
# * Run: git config --global core.excludesfile ~/.gitignore
|
22
|
-
#
|
23
|
-
# After doing this, these files will be ignored in all your git projects,
|
24
|
-
# saving you from having to 'pollute' every project you touch with them
|
25
|
-
#
|
26
|
-
# Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
|
27
|
-
#
|
28
|
-
# For MacOS:
|
29
|
-
#
|
30
|
-
#.DS_Store
|
31
|
-
#
|
32
|
-
# For TextMate
|
33
|
-
#*.tmproj
|
34
|
-
#tmtags
|
35
|
-
#
|
36
|
-
# For emacs:
|
37
|
-
#*~
|
38
|
-
#\#*
|
39
|
-
#.\#*
|
40
|
-
#
|
41
|
-
# For vim:
|
42
|
-
#*.swp
|
data/.travis.yml
DELETED
data/Gemfile
DELETED
data/Gemfile.lock
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
mongoid-ancestry (0.2.3)
|
5
|
-
bson_ext (>= 1.3)
|
6
|
-
mongoid (>= 2.0)
|
7
|
-
|
8
|
-
GEM
|
9
|
-
remote: http://rubygems.org/
|
10
|
-
specs:
|
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)
|
21
|
-
diff-lcs (1.1.2)
|
22
|
-
i18n (0.6.0)
|
23
|
-
mongo (1.6.2)
|
24
|
-
bson (~> 1.6.2)
|
25
|
-
mongoid (2.4.7)
|
26
|
-
activemodel (~> 3.1)
|
27
|
-
mongo (~> 1.3)
|
28
|
-
tzinfo (~> 0.3.22)
|
29
|
-
multi_json (1.3.6)
|
30
|
-
rake (0.9.2.2)
|
31
|
-
rspec (2.5.0)
|
32
|
-
rspec-core (~> 2.5.0)
|
33
|
-
rspec-expectations (~> 2.5.0)
|
34
|
-
rspec-mocks (~> 2.5.0)
|
35
|
-
rspec-core (2.5.1)
|
36
|
-
rspec-expectations (2.5.0)
|
37
|
-
diff-lcs (~> 1.1.2)
|
38
|
-
rspec-mocks (2.5.0)
|
39
|
-
tzinfo (0.3.33)
|
40
|
-
|
41
|
-
PLATFORMS
|
42
|
-
ruby
|
43
|
-
|
44
|
-
DEPENDENCIES
|
45
|
-
mongoid-ancestry!
|
46
|
-
rake
|
47
|
-
rspec (~> 2.5)
|
data/Guardfile
DELETED
@@ -1,10 +0,0 @@
|
|
1
|
-
# A sample Guardfile
|
2
|
-
# More info at https://github.com/guard/guard#readme
|
3
|
-
|
4
|
-
guard 'rspec', :version => 2, :cli => "--format Fuubar" do
|
5
|
-
watch(%r{^spec/.+_spec\.rb})
|
6
|
-
watch(%r{^lib/mongoid-ancestry/(.+)\.rb}) { |m| "spec/lib/mongoid-ancestry/#{m[1]}_spec.rb" }
|
7
|
-
watch('lib/mongoid-ancestry.rb') { "spec" }
|
8
|
-
watch(%r{^spec/support/(.+)\.rb}) { "spec" }
|
9
|
-
watch('spec/spec_helper.rb') { "spec" }
|
10
|
-
end
|
data/MIT-LICENSE
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
Copyright (c) 2009 Stefan Kroes
|
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/Rakefile
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
require 'bundler'
|
2
|
-
Bundler.setup
|
3
|
-
Bundler::GemHelper.install_tasks
|
4
|
-
|
5
|
-
require 'rspec/core'
|
6
|
-
require 'rspec/core/rake_task'
|
7
|
-
RSpec::Core::RakeTask.new(:spec) do |spec|
|
8
|
-
spec.pattern = FileList['spec/**/*_spec.rb']
|
9
|
-
end
|
10
|
-
|
11
|
-
task :default => :spec
|
12
|
-
|
13
|
-
require 'rdoc/task'
|
14
|
-
Rake::RDocTask.new do |rdoc|
|
15
|
-
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
16
|
-
|
17
|
-
rdoc.rdoc_dir = 'rdoc'
|
18
|
-
rdoc.title = "mongoid-ancestry #{version}"
|
19
|
-
rdoc.rdoc_files.include('README*')
|
20
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
-
end
|
data/init.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require 'ancestry'
|
data/install.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
puts "Thank you for installing Ancestry. You can visit http://github.com/stefankroes/ancestry to read the documentation."
|
data/lib/mongoid-ancestry.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
module Mongoid
|
2
|
-
module Ancestry
|
3
|
-
extend ActiveSupport::Concern
|
4
|
-
|
5
|
-
autoload :ClassMethods, 'mongoid-ancestry/class_methods'
|
6
|
-
autoload :Error, 'mongoid-ancestry/exceptions'
|
7
|
-
|
8
|
-
included do
|
9
|
-
cattr_accessor :base_class
|
10
|
-
self.base_class = self
|
11
|
-
end
|
12
|
-
|
13
|
-
require 'mongoid-ancestry/instance_methods'
|
14
|
-
end
|
15
|
-
end
|
@@ -1,212 +0,0 @@
|
|
1
|
-
module Mongoid
|
2
|
-
module Ancestry
|
3
|
-
module ClassMethods
|
4
|
-
def has_ancestry(opts = {})
|
5
|
-
defaults = {
|
6
|
-
:ancestry_field => :ancestry,
|
7
|
-
:cache_depth => false,
|
8
|
-
:depth_cache_field => :ancestry_depth,
|
9
|
-
:orphan_strategy => :destroy
|
10
|
-
}
|
11
|
-
|
12
|
-
valid_opts = [:ancestry_field, :cache_depth, :depth_cache_field, :orphan_strategy]
|
13
|
-
unless opts.is_a?(Hash) && opts.keys.all? {|opt| valid_opts.include?(opt) }
|
14
|
-
raise Error.new("Invalid options for has_ancestry. Only hash is allowed.\n Defaults: #{defaults.inspect}")
|
15
|
-
end
|
16
|
-
|
17
|
-
opts.symbolize_keys!
|
18
|
-
|
19
|
-
opts.reverse_merge!(defaults)
|
20
|
-
|
21
|
-
# Create ancestry field accessor and set to option or default
|
22
|
-
cattr_accessor :ancestry_field
|
23
|
-
self.ancestry_field = opts[:ancestry_field]
|
24
|
-
|
25
|
-
self.field ancestry_field, :type => String
|
26
|
-
self.index ancestry_field
|
27
|
-
|
28
|
-
# Create orphan strategy accessor and set to option or default (writer comes from DynamicClassMethods)
|
29
|
-
cattr_reader :orphan_strategy
|
30
|
-
self.orphan_strategy = opts[:orphan_strategy]
|
31
|
-
|
32
|
-
# Validate format of ancestry column value
|
33
|
-
primary_key_format = opts[:primary_key_format] || /[a-z0-9]+/
|
34
|
-
validates_format_of ancestry_field, :with => /\A#{primary_key_format.source}(\/#{primary_key_format.source})*\Z/, :allow_nil => true
|
35
|
-
|
36
|
-
# Validate that the ancestor ids don't include own id
|
37
|
-
validate :ancestry_exclude_self
|
38
|
-
|
39
|
-
# Create ancestry column accessor and set to option or default
|
40
|
-
if opts[:cache_depth]
|
41
|
-
# Create accessor for column name and set to option or default
|
42
|
-
self.cattr_accessor :depth_cache_field
|
43
|
-
self.depth_cache_field = opts[:depth_cache_field]
|
44
|
-
|
45
|
-
# Cache depth in depth cache column before save
|
46
|
-
before_validation :cache_depth
|
47
|
-
|
48
|
-
# Validate depth column
|
49
|
-
validates_numericality_of depth_cache_field, :greater_than_or_equal_to => 0, :only_integer => true, :allow_nil => false
|
50
|
-
end
|
51
|
-
|
52
|
-
# Create named scopes for depth
|
53
|
-
{:before_depth => 'lt', :to_depth => 'lte', :at_depth => nil, :from_depth => 'gte', :after_depth => 'gt'}.each do |scope_name, operator|
|
54
|
-
scope scope_name, lambda { |depth|
|
55
|
-
raise Error.new("Named scope '#{scope_name}' is only available when depth caching is enabled.") unless opts[:cache_depth]
|
56
|
-
where( (operator ? depth_cache_field.send(operator.to_sym) : depth_cache_field) => depth)
|
57
|
-
}
|
58
|
-
end
|
59
|
-
|
60
|
-
scope :roots, where(ancestry_field => nil)
|
61
|
-
scope :ancestors_of, lambda { |object| where(to_node(object).ancestor_conditions) }
|
62
|
-
scope :children_of, lambda { |object| where(to_node(object).child_conditions) }
|
63
|
-
scope :descendants_of, lambda { |object| any_of(to_node(object).descendant_conditions) }
|
64
|
-
scope :subtree_of, lambda { |object| any_of(to_node(object).subtree_conditions) }
|
65
|
-
scope :siblings_of, lambda { |object| where(to_node(object).sibling_conditions) }
|
66
|
-
scope :ordered_by_ancestry, asc(:"#{self.base_class.ancestry_field}")
|
67
|
-
scope :ordered_by_ancestry_and, lambda {|by| ordered_by_ancestry.order_by([by]) }
|
68
|
-
|
69
|
-
# Update descendants with new ancestry before save
|
70
|
-
before_save :update_descendants_with_new_ancestry
|
71
|
-
|
72
|
-
# Apply orphan strategy before destroy
|
73
|
-
before_destroy :apply_orphan_strategy
|
74
|
-
end
|
75
|
-
|
76
|
-
# Fetch tree node if necessary
|
77
|
-
def to_node object
|
78
|
-
object.is_a?(self.base_class) ? object : find(object)
|
79
|
-
end
|
80
|
-
|
81
|
-
# Scope on relative depth options
|
82
|
-
def scope_depth depth_options, depth
|
83
|
-
depth_options.inject(self.base_class) do |scope, option|
|
84
|
-
scope_name, relative_depth = option
|
85
|
-
if [:before_depth, :to_depth, :at_depth, :from_depth, :after_depth].include? scope_name
|
86
|
-
scope.send scope_name, depth + relative_depth
|
87
|
-
else
|
88
|
-
raise Error.new("Unknown depth option: #{scope_name}.")
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
# Orphan strategy writer
|
94
|
-
def orphan_strategy= orphan_strategy
|
95
|
-
# Check value of orphan strategy, only rootify, restrict or destroy is allowed
|
96
|
-
if [:rootify, :restrict, :destroy].include? orphan_strategy
|
97
|
-
class_variable_set :@@orphan_strategy, orphan_strategy
|
98
|
-
else
|
99
|
-
raise Error.new("Invalid orphan strategy, valid ones are :rootify, :restrict and :destroy.")
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
# Arrangement
|
104
|
-
def arrange options = {}
|
105
|
-
scope =
|
106
|
-
if options[:order].nil?
|
107
|
-
self.base_class.ordered_by_ancestry
|
108
|
-
else
|
109
|
-
self.base_class.ordered_by_ancestry_and options.delete(:order)
|
110
|
-
end
|
111
|
-
# Get all nodes ordered by ancestry and start sorting them into an empty hash
|
112
|
-
scope.all(options).inject(ActiveSupport::OrderedHash.new) do |arranged_nodes, node|
|
113
|
-
# Find the insertion point for that node by going through its ancestors
|
114
|
-
node.ancestor_ids.inject(arranged_nodes) do |insertion_point, ancestor_id|
|
115
|
-
insertion_point.each do |parent, children|
|
116
|
-
# Change the insertion point to children if node is a descendant of this parent
|
117
|
-
insertion_point = children if ancestor_id == parent.id
|
118
|
-
end; insertion_point
|
119
|
-
end[node] = ActiveSupport::OrderedHash.new; arranged_nodes
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
# Integrity checking
|
124
|
-
def check_ancestry_integrity! options = {}
|
125
|
-
parents = {}
|
126
|
-
exceptions = [] if options[:report] == :list
|
127
|
-
# For each node ...
|
128
|
-
self.base_class.all.each do |node|
|
129
|
-
begin
|
130
|
-
# ... check validity of ancestry column
|
131
|
-
if !node.valid? and !node.errors[node.class.ancestry_field].blank?
|
132
|
-
raise IntegrityError.new "Invalid format for ancestry column of node #{node.id}: #{node.read_attribute node.ancestry_field}."
|
133
|
-
end
|
134
|
-
# ... check that all ancestors exist
|
135
|
-
node.ancestor_ids.each do |ancestor_id|
|
136
|
-
unless where(:_id => ancestor_id).first
|
137
|
-
raise IntegrityError.new "Reference to non-existent node in node #{node.id}: #{ancestor_id}."
|
138
|
-
end
|
139
|
-
end
|
140
|
-
# ... check that all node parents are consistent with values observed earlier
|
141
|
-
node.path_ids.zip([nil] + node.path_ids).each do |node_id, parent_id|
|
142
|
-
parents[node_id] = parent_id unless parents.has_key? node_id
|
143
|
-
unless parents[node_id] == parent_id
|
144
|
-
raise IntegrityError.new "Conflicting parent id found in node #{node.id}: #{parent_id || 'nil'} for node #{node_id} while expecting #{parents[node_id] || 'nil'}"
|
145
|
-
end
|
146
|
-
end
|
147
|
-
rescue IntegrityError => integrity_exception
|
148
|
-
case options[:report]
|
149
|
-
when :list then exceptions << integrity_exception
|
150
|
-
when :echo then puts integrity_exception
|
151
|
-
else raise integrity_exception
|
152
|
-
end
|
153
|
-
end
|
154
|
-
end
|
155
|
-
exceptions if options[:report] == :list
|
156
|
-
end
|
157
|
-
|
158
|
-
# Integrity restoration
|
159
|
-
def restore_ancestry_integrity!
|
160
|
-
parents = {}
|
161
|
-
# For each node ...
|
162
|
-
self.base_class.all.each do |node|
|
163
|
-
# ... set its ancestry to nil if invalid
|
164
|
-
if node.errors[node.class.ancestry_field].blank?
|
165
|
-
node.without_ancestry_callbacks do
|
166
|
-
node.update_attribute node.ancestry_field, nil
|
167
|
-
end
|
168
|
-
end
|
169
|
-
# ... save parent of this node in parents array if it exists
|
170
|
-
parents[node.id] = node.parent_id if exists? node.parent_id
|
171
|
-
|
172
|
-
# Reset parent id in array to nil if it introduces a cycle
|
173
|
-
parent = parents[node.id]
|
174
|
-
until parent.nil? || parent == node.id
|
175
|
-
parent = parents[parent]
|
176
|
-
end
|
177
|
-
parents[node.id] = nil if parent == node.id
|
178
|
-
end
|
179
|
-
# For each node ...
|
180
|
-
self.base_class.all.each do |node|
|
181
|
-
# ... rebuild ancestry from parents array
|
182
|
-
ancestry, parent = nil, parents[node.id]
|
183
|
-
until parent.nil?
|
184
|
-
ancestry, parent = if ancestry.nil? then parent else "#{parent}/#{ancestry}" end, parents[parent]
|
185
|
-
end
|
186
|
-
node.without_ancestry_callbacks do
|
187
|
-
node.update_attribute node.ancestry_field, ancestry
|
188
|
-
end
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
# Build ancestry from parent id's for migration purposes
|
193
|
-
def build_ancestry_from_parent_ids! parent_id = nil, ancestry = nil
|
194
|
-
self.base_class.where(:parent_id => parent_id).all.each do |node|
|
195
|
-
node.without_ancestry_callbacks do
|
196
|
-
node.update_attribute(self.base_class.ancestry_field, ancestry)
|
197
|
-
end
|
198
|
-
build_ancestry_from_parent_ids! node.id,
|
199
|
-
if ancestry.nil? then node.id.to_s else "#{ancestry}/#{node.id}" end
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
# Rebuild depth cache if it got corrupted or if depth caching was just turned on
|
204
|
-
def rebuild_depth_cache!
|
205
|
-
raise Error.new("Cannot rebuild depth cache for model without depth caching.") unless respond_to? :depth_cache_field
|
206
|
-
self.base_class.all.each do |node|
|
207
|
-
node.update_attribute depth_cache_field, node.depth
|
208
|
-
end
|
209
|
-
end
|
210
|
-
end
|
211
|
-
end
|
212
|
-
end
|