mongoid-ancestry-fixes 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- Yzc5YjFkNWJjNWM2MDZmNGU3NmY4NWY1NmZlZGEwZGE4MjkyYTI2Mg==
4
+ ZmM5YTM5MDAwNjg4NmRhYzRlNzEzOTY4YmMzYjgzODhhMTMzYTJkMQ==
5
5
  data.tar.gz: !binary |-
6
- Y2FlMDMyNWZlM2U2ZWZjNGM0ODU4YjIzYjk2Y2M5ZTIzMzdhOTdmOQ==
6
+ MjZiMWQ3MTU4NzZkNWExNmU4YTY4NzVkNzI0YzI4MzEwOWRiNjNiOQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- OTljNjA5NDUxODZkYTI2YzZhOTAzZTBkZGE3ZDYyZWU0YmFiODk5OTYwNmJm
10
- OWFhZTRiMWE0MmVlMGEwZThiZmY1YTQ3NDg0MGRkMDUyNjBkNzdkYmNjMjRh
11
- ZWE4NTk0MzhkNzBkZjY4MzI3MmZlZjRjY2YwZjIwYjc4MTM3YTk=
9
+ NTdlNmUxYWFkZmNkMTU5ZjkxZWQ5MDM4ZTFkMzk5NDczYjE2NmFmZTJjMWUy
10
+ OWRiMWQxNzMwMGEwZWNiNGU1N2JhY2IyM2Q3NGNkY2EyMDI1NGVkNzcxMGI5
11
+ ZDEwZjlhMzgzY2MxNGI5NjZhMWM3YzNmNjhmYWE5MWVjMjJhNGM=
12
12
  data.tar.gz: !binary |-
13
- ZDBiMDNhYzQ5YzBmZTA2YWVkY2ZhMGFhOTI1ZDMwODFiYWM5ZmZmMjMzOTI4
14
- YjYxZjM5ZDIyNmVjYzZlYTM4ZjhkZGRiMDEwZGIyMmM4OWIyYTY0NzY5ODhh
15
- NGMwYTg3MjI2YThkMjRmM2Y1ZmU4N2E5YmE3ZjgxNmIzYWM4MjA=
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.1
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: Ancestry allows the records of a Mongoid model to be organised in a tree
96
- structure, using a single, intuitively formatted database field. It exposes all
97
- the standard tree structure relations (ancestors, parent, root, children, siblings,
98
- descendants) and all of them can be fetched in a single query. Additional features
99
- are named_scopes, integrity checking, integrity restoration, arrangement of (sub)tree
100
- into hashes and different strategies for dealing with orphaned records.
101
- test_files:
102
- - spec/lib/ancestry_spec.rb
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
@@ -1,3 +0,0 @@
1
- rvm:
2
- - 1.9.2
3
- - 1.9.3
data/Gemfile DELETED
@@ -1,8 +0,0 @@
1
- source :rubygems
2
-
3
- gemspec
4
-
5
- group :test do
6
- gem 'rake'
7
- gem 'rspec', '~> 2.5'
8
- end
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."
@@ -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