nested_set 1.6.1 → 1.6.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +1 -1
- data/VERSION +1 -1
- data/lib/nested_set/base.rb +10 -0
- data/lib/nested_set/depth.rb +4 -1
- data/lib/nested_set/helper.rb +9 -12
- data/nested_set.gemspec +2 -2
- data/test/benchmarks.rb +1 -1
- data/test/db/schema.rb +4 -3
- data/test/fixtures/categories.yml +6 -0
- data/test/nested_set_test.rb +37 -2
- metadata +4 -4
data/README.md
CHANGED
@@ -66,7 +66,7 @@ or sorted select:
|
|
66
66
|
|
67
67
|
<%= f.select :parent_id, sorted_nested_set_options(Category, lambda(&:name)) {|i, level| "#{'-' * level} #{i.name}" } %>
|
68
68
|
|
69
|
-
<% sort_method = lambda{|x
|
69
|
+
<% sort_method = lambda{|x| x.name.downcase} %>
|
70
70
|
|
71
71
|
NOTE: to sort UTF-8 strings you should use `x.name.mb_chars.downcase`
|
72
72
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.6.
|
1
|
+
1.6.2
|
data/lib/nested_set/base.rb
CHANGED
@@ -28,6 +28,7 @@ module CollectiveIdea #:nodoc:
|
|
28
28
|
# * +:parent_column+ - specifies the column name to use for keeping the position integer (default: parent_id)
|
29
29
|
# * +:left_column+ - column name for left boundry data, default "lft"
|
30
30
|
# * +:right_column+ - column name for right boundry data, default "rgt"
|
31
|
+
# * +:depth_column+ - column name for level cache data, default "depth"
|
31
32
|
# * +:scope+ - restricts what is to be considered a list. Given a symbol, it'll attach "_id"
|
32
33
|
# (if it hasn't been already) and use that as the foreign key restriction. You
|
33
34
|
# can also pass an array to scope by multiple attributes.
|
@@ -45,6 +46,7 @@ module CollectiveIdea #:nodoc:
|
|
45
46
|
:parent_column => 'parent_id',
|
46
47
|
:left_column => 'lft',
|
47
48
|
:right_column => 'rgt',
|
49
|
+
:depth_column => 'depth',
|
48
50
|
:dependent => :delete_all, # or :destroy
|
49
51
|
}.merge(options)
|
50
52
|
|
@@ -287,6 +289,10 @@ module CollectiveIdea #:nodoc:
|
|
287
289
|
Array(acts_as_nested_set_options[:scope])
|
288
290
|
end
|
289
291
|
|
292
|
+
def depth_column_name
|
293
|
+
acts_as_nested_set_options[:depth_column]
|
294
|
+
end
|
295
|
+
|
290
296
|
def quoted_left_column_name
|
291
297
|
connection.quote_column_name(left_column_name)
|
292
298
|
end
|
@@ -302,6 +308,10 @@ module CollectiveIdea #:nodoc:
|
|
302
308
|
def quoted_scope_column_names
|
303
309
|
scope_column_names.collect {|column_name| connection.quote_column_name(column_name) }
|
304
310
|
end
|
311
|
+
|
312
|
+
def quoted_depth_column_name
|
313
|
+
connection.quote_column_name(depth_column_name)
|
314
|
+
end
|
305
315
|
end
|
306
316
|
|
307
317
|
# Any instance method that returns a collection makes use of Rails 2.1's named_scope (which is bundled for Rails 2.0), so it can be treated as a finder.
|
data/lib/nested_set/depth.rb
CHANGED
@@ -21,7 +21,10 @@ module CollectiveIdea #:nodoc:
|
|
21
21
|
|
22
22
|
# Update cached_level attribute
|
23
23
|
def update_depth
|
24
|
-
|
24
|
+
depth_delta = level - depth
|
25
|
+
if depth_delta != 0
|
26
|
+
self.self_and_descendants.update_all(["#{self.class.quoted_depth_column_name} = #{self.class.quoted_depth_column_name} + ?", depth_delta])
|
27
|
+
end
|
25
28
|
end
|
26
29
|
|
27
30
|
# Update cached_level attribute for all record tree
|
data/lib/nested_set/helper.rb
CHANGED
@@ -26,7 +26,6 @@ module CollectiveIdea #:nodoc:
|
|
26
26
|
items = Array(class_or_item)
|
27
27
|
result = []
|
28
28
|
items.each do |item|
|
29
|
-
levels = []
|
30
29
|
item.self_and_descendants.each_with_level do |i, level|
|
31
30
|
if mover.nil? || mover.new_record? || mover.move_possible?(i)
|
32
31
|
result.push([yield(i, level), i.id])
|
@@ -55,28 +54,26 @@ module CollectiveIdea #:nodoc:
|
|
55
54
|
#
|
56
55
|
# OR
|
57
56
|
#
|
58
|
-
# sort_method = lambda{|x
|
57
|
+
# sort_method = lambda{|x| x.name.mb_chars.downcase }
|
59
58
|
#
|
60
59
|
# <%= f.select :parent_id, nested_set_options(Category, sort_method) {|i, level|
|
61
60
|
# "#{'–' * level} #{i.name}"
|
62
61
|
# }) %>
|
63
62
|
#
|
64
63
|
def sorted_nested_set_options(class_or_item, sort_proc, mover = nil, level = 0)
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
end
|
72
|
-
result
|
64
|
+
hash = if class_or_item.is_a?(Class)
|
65
|
+
class_or_item
|
66
|
+
else
|
67
|
+
class_or_item.self_and_descendants
|
68
|
+
end.arrange
|
69
|
+
build_node(hash, sort_proc, mover, level){|x, lvl| yield(x, lvl)}
|
73
70
|
end
|
74
71
|
|
75
72
|
def build_node(hash, sort_proc, mover = nil, level = nil)
|
76
|
-
result
|
73
|
+
result = []
|
77
74
|
hash.keys.sort_by(&sort_proc).each do |node|
|
78
75
|
if mover.nil? || mover.new_record? || mover.move_possible?(node)
|
79
|
-
result
|
76
|
+
result.push([yield(node, level.to_i), node.id])
|
80
77
|
result.push(*build_node(hash[node], sort_proc, mover, level.to_i + 1){|x, lvl| yield(x, lvl)})
|
81
78
|
end
|
82
79
|
end if hash.present?
|
data/nested_set.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{nested_set}
|
8
|
-
s.version = "1.6.
|
8
|
+
s.version = "1.6.2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Brandon Keepers", "Daniel Morrison"]
|
12
|
-
s.date = %q{2010-12-
|
12
|
+
s.date = %q{2010-12-23}
|
13
13
|
s.description = %q{An awesome nested set implementation for Active Record}
|
14
14
|
s.email = %q{info@collectiveidea.com}
|
15
15
|
s.extra_rdoc_files = [
|
data/test/benchmarks.rb
CHANGED
@@ -49,7 +49,7 @@ if $0 == __FILE__
|
|
49
49
|
end
|
50
50
|
|
51
51
|
measure "sorted_nested_set_options" do
|
52
|
-
sorted_nested_set_options(Category, lambda
|
52
|
+
sorted_nested_set_options(Category, lambda{|x| x.name }){|i, level| "#{'-' * level} #{i.name}" }
|
53
53
|
end
|
54
54
|
|
55
55
|
end
|
data/test/db/schema.rb
CHANGED
@@ -5,14 +5,14 @@ ActiveRecord::Schema.define(:version => 0) do
|
|
5
5
|
t.column :parent_id, :integer
|
6
6
|
t.column :lft, :integer
|
7
7
|
t.column :rgt, :integer
|
8
|
-
t.column :depth, :integer, :default => 0
|
9
8
|
t.column :organization_id, :integer
|
9
|
+
t.column :depth, :integer, :default => 0
|
10
10
|
end
|
11
11
|
|
12
12
|
create_table :departments, :force => true do |t|
|
13
13
|
t.column :name, :string
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
create_table :notes, :force => true do |t|
|
17
17
|
t.column :body, :text
|
18
18
|
t.column :parent_id, :integer
|
@@ -21,11 +21,12 @@ ActiveRecord::Schema.define(:version => 0) do
|
|
21
21
|
t.column :notable_id, :integer
|
22
22
|
t.column :notable_type, :string
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
create_table :renamed_columns, :force => true do |t|
|
26
26
|
t.column :name, :string
|
27
27
|
t.column :mother_id, :integer
|
28
28
|
t.column :red, :integer
|
29
29
|
t.column :black, :integer
|
30
|
+
t.column :level, :integer
|
30
31
|
end
|
31
32
|
end
|
@@ -14,32 +14,38 @@ top_level:
|
|
14
14
|
name: Top Level
|
15
15
|
lft: 1
|
16
16
|
rgt: 10
|
17
|
+
depth: 0
|
17
18
|
child_1:
|
18
19
|
id: 2
|
19
20
|
name: Child 1
|
20
21
|
parent_id: 1
|
21
22
|
lft: 2
|
22
23
|
rgt: 3
|
24
|
+
depth: 1
|
23
25
|
child_2:
|
24
26
|
id: 3
|
25
27
|
name: Child 2
|
26
28
|
parent_id: 1
|
27
29
|
lft: 4
|
28
30
|
rgt: 7
|
31
|
+
depth: 1
|
29
32
|
child_2_1:
|
30
33
|
id: 4
|
31
34
|
name: Child 2.1
|
32
35
|
parent_id: 3
|
33
36
|
lft: 5
|
34
37
|
rgt: 6
|
38
|
+
depth: 2
|
35
39
|
child_3:
|
36
40
|
id: 5
|
37
41
|
name: Child 3
|
38
42
|
parent_id: 1
|
39
43
|
lft: 8
|
40
44
|
rgt: 9
|
45
|
+
depth: 1
|
41
46
|
top_level_2:
|
42
47
|
id: 6
|
43
48
|
name: Top Level 2
|
44
49
|
lft: 11
|
45
50
|
rgt: 12
|
51
|
+
depth: 0
|
data/test/nested_set_test.rb
CHANGED
@@ -15,7 +15,7 @@ class ScopedCategory < ActiveRecord::Base
|
|
15
15
|
end
|
16
16
|
|
17
17
|
class RenamedColumns < ActiveRecord::Base
|
18
|
-
acts_as_nested_set :parent_column => 'mother_id', :left_column => 'red', :right_column => 'black'
|
18
|
+
acts_as_nested_set :parent_column => 'mother_id', :left_column => 'red', :right_column => 'black', :depth_column => 'level'
|
19
19
|
end
|
20
20
|
|
21
21
|
class NestedSetTest < ActiveSupport::TestCase
|
@@ -32,11 +32,15 @@ class NestedSetTest < ActiveSupport::TestCase
|
|
32
32
|
assert_equal 'parent_id', Default.acts_as_nested_set_options[:parent_column]
|
33
33
|
end
|
34
34
|
|
35
|
+
def test_depth_column_default
|
36
|
+
assert_equal 'depth', Default.acts_as_nested_set_options[:depth_column]
|
37
|
+
end
|
38
|
+
|
35
39
|
def test_scope_default
|
36
40
|
assert_nil Default.acts_as_nested_set_options[:scope]
|
37
41
|
end
|
38
42
|
|
39
|
-
def
|
43
|
+
def test_left_column_default
|
40
44
|
assert_equal 'lft', Default.left_column_name
|
41
45
|
assert_equal 'lft', Default.new.left_column_name
|
42
46
|
assert_equal 'red', RenamedColumns.left_column_name
|
@@ -57,6 +61,13 @@ class NestedSetTest < ActiveSupport::TestCase
|
|
57
61
|
assert_equal 'mother_id', RenamedColumns.new.parent_column_name
|
58
62
|
end
|
59
63
|
|
64
|
+
def test_depth_column_name
|
65
|
+
assert_equal 'depth', Default.depth_column_name
|
66
|
+
assert_equal 'depth', Default.new.depth_column_name
|
67
|
+
assert_equal 'level', RenamedColumns.depth_column_name
|
68
|
+
assert_equal 'level', RenamedColumns.new.depth_column_name
|
69
|
+
end
|
70
|
+
|
60
71
|
def test_creation_with_altered_column_names
|
61
72
|
assert_nothing_raised do
|
62
73
|
RenamedColumns.create!()
|
@@ -75,6 +86,12 @@ class NestedSetTest < ActiveSupport::TestCase
|
|
75
86
|
assert_equal quoted, Default.new.quoted_right_column_name
|
76
87
|
end
|
77
88
|
|
89
|
+
def test_quoted_depth_column_name
|
90
|
+
quoted = Default.connection.quote_column_name('depth')
|
91
|
+
assert_equal quoted, Default.quoted_depth_column_name
|
92
|
+
assert_equal quoted, Default.new.quoted_depth_column_name
|
93
|
+
end
|
94
|
+
|
78
95
|
def test_left_column_protected_from_assignment
|
79
96
|
assert_raises(ActiveRecord::ActiveRecordError) { Category.new.lft = 1 }
|
80
97
|
end
|
@@ -174,6 +191,24 @@ class NestedSetTest < ActiveSupport::TestCase
|
|
174
191
|
assert_equal 2, categories(:child_2_1).level
|
175
192
|
end
|
176
193
|
|
194
|
+
def test_depth
|
195
|
+
assert_equal 0, categories(:top_level).depth
|
196
|
+
assert_equal 1, categories(:child_1).depth
|
197
|
+
assert_equal 2, categories(:child_2_1).depth
|
198
|
+
end
|
199
|
+
|
200
|
+
def test_depth_after_move
|
201
|
+
categories(:child_2).move_to_root
|
202
|
+
|
203
|
+
assert_equal 0, categories(:child_2).reload.depth
|
204
|
+
assert_equal 1, categories(:child_2_1).reload.depth
|
205
|
+
|
206
|
+
categories(:child_2).move_to_child_of(categories(:top_level_2))
|
207
|
+
|
208
|
+
assert_equal 1, categories(:child_2).reload.depth
|
209
|
+
assert_equal 2, categories(:child_2_1).reload.depth
|
210
|
+
end
|
211
|
+
|
177
212
|
def test_has_children?
|
178
213
|
assert categories(:child_2_1).children.empty?
|
179
214
|
assert !categories(:child_2).children.empty?
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 1
|
7
7
|
- 6
|
8
|
-
-
|
9
|
-
version: 1.6.
|
8
|
+
- 2
|
9
|
+
version: 1.6.2
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Brandon Keepers
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-12-
|
18
|
+
date: 2010-12-23 00:00:00 +03:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -153,7 +153,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
153
153
|
requirements:
|
154
154
|
- - ">="
|
155
155
|
- !ruby/object:Gem::Version
|
156
|
-
hash:
|
156
|
+
hash: 754987949
|
157
157
|
segments:
|
158
158
|
- 0
|
159
159
|
version: "0"
|