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 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