awesome_nested_set 3.0.3 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +4 -1
- data/README.md +5 -3
- data/lib/awesome_nested_set/columns.rb +4 -0
- data/lib/awesome_nested_set/model.rb +17 -3
- data/lib/awesome_nested_set/model/movable.rb +2 -1
- data/lib/awesome_nested_set/model/prunable.rb +1 -1
- data/lib/awesome_nested_set/model/transactable.rb +1 -1
- data/lib/awesome_nested_set/model/validatable.rb +13 -2
- data/lib/awesome_nested_set/tree.rb +11 -1
- data/lib/awesome_nested_set/version.rb +1 -1
- metadata +10 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ddb25974895907e5a9dd2e701894678e7f14f338
|
4
|
+
data.tar.gz: 806590f9ab37cbc3756f15e613b4ae6226cab542
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d2e80c6b55ce284b9e151a1a4ba02246284cd1718e3aea16f3a5cb5419cfb4743c826537ceb0a0f0ae2f735eaa177f991b1b0035de6acb99e4357acedca74584
|
7
|
+
data.tar.gz: 08bc67738a4b4401aa49bcb9ef6098b0361e10d3bb2b4e916dd69f58020c7a994a7c0db6cb428bcf1fbfbefd567690c45f8b89b17ed83d953f4d800125c770c1
|
data/CHANGELOG
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
-
3.0
|
1
|
+
3.1.0
|
2
|
+
* Ensure that nested_set queries respect the model's default_scope. [oesgalha](https://github.com/oesgalha)
|
3
|
+
* Add Rails 5 support [Krzysztof Rybka](https://github.com/krzysiek1507)
|
4
|
+
* Fix .all_roots_valid? method when model is ordered by default [Adam Hodowany](https://github.com/hodak)
|
2
5
|
* Reuse the current model's connection when available [Tim Bugai] [#322](https://github.com/collectiveidea/awesome_nested_set/pull/322)
|
3
6
|
|
4
7
|
3.0.3
|
data/README.md
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
Awesome Nested Set is an implementation of the nested set pattern for ActiveRecord models.
|
7
7
|
It is a replacement for acts_as_nested_set and BetterNestedSet, but more awesome.
|
8
8
|
|
9
|
-
Version 3 supports Rails 4. Version 2 supports Rails 3. Gem versions prior to 2.0 support Rails 2.
|
9
|
+
Version 3.1 supports Rails 5 & 4. Version 2 supports Rails 3. Gem versions prior to 2.0 support Rails 2.
|
10
10
|
|
11
11
|
## What makes this so awesome?
|
12
12
|
|
@@ -26,6 +26,8 @@ gem 'awesome_nested_set'
|
|
26
26
|
To make use of `awesome_nested_set` your model needs to have 3 fields:
|
27
27
|
`lft`, `rgt`, and `parent_id`. The names of these fields are configurable.
|
28
28
|
You can also have optional fields: `depth` and `children_count`. These fields are configurable.
|
29
|
+
Note that the `childrent_count` column must have `null: false` and `default: 0` to
|
30
|
+
function properly.
|
29
31
|
|
30
32
|
```ruby
|
31
33
|
class CreateCategories < ActiveRecord::Migration
|
@@ -66,7 +68,7 @@ You can pass various options to `acts_as_nested_set` macro. Configuration option
|
|
66
68
|
* `left_column`: column name for left boundary data (default: lft)
|
67
69
|
* `right_column`: column name for right boundary data (default: rgt)
|
68
70
|
* `depth_column`: column name for the depth data default (default: depth)
|
69
|
-
* `scope`: restricts what is to be considered a list. Given a symbol, it'll attach
|
71
|
+
* `scope`: restricts what is to be considered a list. Given a symbol, it'll attach `_id` (if it hasn't been already) and use that as the foreign key restriction. You can also pass an array to scope by multiple attributes. Example: `acts_as_nested_set :scope => [:notable_id, :notable_type]`
|
70
72
|
* `dependent`: behavior for cascading destroy. If set to :destroy, all the child objects are destroyed alongside this object by calling their destroy method. If set to :delete_all (default), all the child objects are deleted without calling their destroy method. If set to :nullify, all child objects will become orphaned and become roots themselves.
|
71
73
|
* `counter_cache`: adds a counter cache for the number of children. defaults to false. Example: `acts_as_nested_set :counter_cache => :children_count`
|
72
74
|
* `order_column`: on which column to do sorting, by default it is the left_column_name. Example: `acts_as_nested_set :order_column => :position`
|
@@ -237,4 +239,4 @@ You can learn more about nested sets at: http://threebit.net/tutorials/nestedset
|
|
237
239
|
|
238
240
|
Please see the ['Contributing' document](CONTRIBUTING.md).
|
239
241
|
|
240
|
-
Copyright © 2008
|
242
|
+
Copyright © 2008–2015 [Collective Idea](http://collectiveidea.com), released under the MIT license.
|
@@ -31,6 +31,10 @@ module CollectiveIdea #:nodoc:
|
|
31
31
|
Array(acts_as_nested_set_options[:scope])
|
32
32
|
end
|
33
33
|
|
34
|
+
def counter_cache_column_name
|
35
|
+
acts_as_nested_set_options[:counter_cache]
|
36
|
+
end
|
37
|
+
|
34
38
|
def quoted_left_column_name
|
35
39
|
model_connection.quote_column_name(left_column_name)
|
36
40
|
end
|
@@ -145,7 +145,7 @@ module CollectiveIdea #:nodoc:
|
|
145
145
|
end
|
146
146
|
end
|
147
147
|
|
148
|
-
self.class.base_class.
|
148
|
+
self.class.base_class.nested_set_scope options
|
149
149
|
end
|
150
150
|
|
151
151
|
# Separate an other `nested_set_scope` for unscoped model
|
@@ -154,7 +154,7 @@ module CollectiveIdea #:nodoc:
|
|
154
154
|
# And class level `nested_set_scope` seems just for query `root` `child` .. etc
|
155
155
|
# I think we don't have to provide unscoped `nested_set_scope` in class level.
|
156
156
|
def nested_set_scope_without_default_scope(*args)
|
157
|
-
self.class.unscoped do
|
157
|
+
self.class.base_class.unscoped do
|
158
158
|
nested_set_scope(*args)
|
159
159
|
end
|
160
160
|
end
|
@@ -182,7 +182,7 @@ module CollectiveIdea #:nodoc:
|
|
182
182
|
end
|
183
183
|
|
184
184
|
def right_most_node
|
185
|
-
@right_most_node ||=
|
185
|
+
@right_most_node ||= nested_set_scope_without_default_scope(
|
186
186
|
:order => "#{quoted_right_column_full_name} desc"
|
187
187
|
).first
|
188
188
|
end
|
@@ -232,6 +232,20 @@ module CollectiveIdea #:nodoc:
|
|
232
232
|
end
|
233
233
|
end
|
234
234
|
|
235
|
+
def update_counter_cache
|
236
|
+
return unless acts_as_nested_set_options[:counter_cache]
|
237
|
+
|
238
|
+
# Decrease the counter for all old parents
|
239
|
+
if old_parent = self.parent
|
240
|
+
self.class.decrement_counter(acts_as_nested_set_options[:counter_cache], old_parent)
|
241
|
+
end
|
242
|
+
|
243
|
+
# Increase the counter for all new parents
|
244
|
+
if new_parent = self.reload.parent
|
245
|
+
self.class.increment_counter(acts_as_nested_set_options[:counter_cache], new_parent)
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
235
249
|
def set_default_left_and_right
|
236
250
|
# adds the new node to the right of all existing nodes
|
237
251
|
self[left_column_name] = right_most_bound + 1
|
@@ -46,7 +46,7 @@ module CollectiveIdea #:nodoc:
|
|
46
46
|
elsif node.children.count == index
|
47
47
|
move_to_right_of(node.children.last)
|
48
48
|
else
|
49
|
-
my_position = node.children.index(self)
|
49
|
+
my_position = node.children.to_a.index(self)
|
50
50
|
if my_position && my_position < index
|
51
51
|
# e.g. if self is at position 0 and we want to move self to position 1 then self
|
52
52
|
# needs to move to the *right* of the node at position 1. That's because the node
|
@@ -105,6 +105,7 @@ module CollectiveIdea #:nodoc:
|
|
105
105
|
self.reload_nested_set
|
106
106
|
|
107
107
|
Move.new(target, position, self).move
|
108
|
+
update_counter_cache
|
108
109
|
end
|
109
110
|
after_move_to(target, position)
|
110
111
|
end
|
@@ -47,7 +47,7 @@ module CollectiveIdea #:nodoc:
|
|
47
47
|
elsif acts_as_nested_set_options[:dependent] == :restrict_with_error
|
48
48
|
unless leaf?
|
49
49
|
record = self.class.human_attribute_name(:children).downcase
|
50
|
-
errors.add(:base, :"restrict_dependent_destroy
|
50
|
+
errors.add(:base, :"restrict_dependent_destroy.#{Rails::VERSION::MAJOR < 5 ? 'many' : 'has_many'}", record: record)
|
51
51
|
return false
|
52
52
|
end
|
53
53
|
return true
|
@@ -17,7 +17,7 @@ module CollectiveIdea #:nodoc:
|
|
17
17
|
rescue CollectiveIdea::Acts::NestedSet::Move::ImpossibleMove
|
18
18
|
raise
|
19
19
|
rescue ActiveRecord::StatementInvalid => error
|
20
|
-
raise OpenTransactionsIsNotZero.new(error.message) unless connection.open_transactions.zero?
|
20
|
+
raise OpenTransactionsIsNotZero.new(error.message) unless self.class.connection.open_transactions.zero?
|
21
21
|
raise unless error.message =~ /[Dd]eadlock|Lock wait timeout exceeded/
|
22
22
|
raise DeadlockDetected.new(error.message) unless retry_count < 10
|
23
23
|
retry_count += 1
|
@@ -41,8 +41,10 @@ module CollectiveIdea
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def each_root_valid?(roots_to_validate)
|
44
|
+
left_column = acts_as_nested_set_options[:left_column]
|
45
|
+
reordered_roots = roots_reordered_by_column(roots_to_validate, left_column)
|
44
46
|
left = right = 0
|
45
|
-
|
47
|
+
reordered_roots.all? do |root|
|
46
48
|
(root.left > left && root.right > right).tap do
|
47
49
|
left = root.left
|
48
50
|
right = root.right
|
@@ -57,12 +59,21 @@ module CollectiveIdea
|
|
57
59
|
}
|
58
60
|
end
|
59
61
|
|
62
|
+
def roots_reordered_by_column(roots_to_reorder, column)
|
63
|
+
if roots_to_reorder.respond_to?(:reorder) # ActiveRecord's relation
|
64
|
+
roots_to_reorder.reorder(column)
|
65
|
+
elsif roots_to_reorder.respond_to?(:sort) # Array
|
66
|
+
roots_to_reorder.sort { |a, b| a.send(column) <=> b.send(column) }
|
67
|
+
else
|
68
|
+
roots_to_reorder
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
60
72
|
def scope_string
|
61
73
|
Array(acts_as_nested_set_options[:scope]).map do |c|
|
62
74
|
connection.quote_column_name(c)
|
63
75
|
end.push(nil).join(", ")
|
64
76
|
end
|
65
|
-
|
66
77
|
end
|
67
78
|
end
|
68
79
|
end
|
@@ -6,7 +6,7 @@ module CollectiveIdea #:nodoc:
|
|
6
6
|
attr_accessor :indices
|
7
7
|
|
8
8
|
delegate :left_column_name, :right_column_name, :quoted_parent_column_full_name,
|
9
|
-
:order_for_rebuild, :scope_for_rebuild,
|
9
|
+
:order_for_rebuild, :scope_for_rebuild, :counter_cache_column_name,
|
10
10
|
:to => :model
|
11
11
|
|
12
12
|
def initialize(model, validate_nodes)
|
@@ -23,6 +23,7 @@ module CollectiveIdea #:nodoc:
|
|
23
23
|
# setup index for this scope
|
24
24
|
indices[scope_for_rebuild.call(root_node)] ||= 0
|
25
25
|
set_left_and_rights(root_node)
|
26
|
+
reset_counter_cache(root_node)
|
26
27
|
end
|
27
28
|
end
|
28
29
|
|
@@ -57,6 +58,15 @@ module CollectiveIdea #:nodoc:
|
|
57
58
|
def set_right!(node)
|
58
59
|
node[right_column_name] = increment_indice!(node)
|
59
60
|
end
|
61
|
+
|
62
|
+
def reset_counter_cache(node)
|
63
|
+
return unless counter_cache_column_name
|
64
|
+
node.class.reset_counters(node.id, :children)
|
65
|
+
|
66
|
+
node.children.each do |child|
|
67
|
+
reset_counter_cache(child)
|
68
|
+
end
|
69
|
+
end
|
60
70
|
end
|
61
71
|
end
|
62
72
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: awesome_nested_set
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0
|
4
|
+
version: 3.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brandon Keepers
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2016-
|
13
|
+
date: 2016-05-27 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
@@ -21,7 +21,7 @@ dependencies:
|
|
21
21
|
version: 4.0.0
|
22
22
|
- - "<"
|
23
23
|
- !ruby/object:Gem::Version
|
24
|
-
version: '5'
|
24
|
+
version: '5.1'
|
25
25
|
type: :runtime
|
26
26
|
prerelease: false
|
27
27
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -31,21 +31,21 @@ dependencies:
|
|
31
31
|
version: 4.0.0
|
32
32
|
- - "<"
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version: '5'
|
34
|
+
version: '5.1'
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: rspec-rails
|
37
37
|
requirement: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
|
-
- -
|
39
|
+
- - '='
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version:
|
41
|
+
version: 3.5.0.beta3
|
42
42
|
type: :development
|
43
43
|
prerelease: false
|
44
44
|
version_requirements: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
|
-
- -
|
46
|
+
- - '='
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version:
|
48
|
+
version: 3.5.0.beta3
|
49
49
|
- !ruby/object:Gem::Dependency
|
50
50
|
name: rake
|
51
51
|
requirement: !ruby/object:Gem::Requirement
|
@@ -130,7 +130,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
130
130
|
requirements:
|
131
131
|
- - ">="
|
132
132
|
- !ruby/object:Gem::Version
|
133
|
-
version:
|
133
|
+
version: 2.0.0
|
134
134
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
136
|
- - ">="
|
@@ -138,7 +138,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
138
138
|
version: '0'
|
139
139
|
requirements: []
|
140
140
|
rubyforge_project:
|
141
|
-
rubygems_version: 2.
|
141
|
+
rubygems_version: 2.6.2
|
142
142
|
signing_key:
|
143
143
|
specification_version: 4
|
144
144
|
summary: An awesome nested set implementation for Active Record
|