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 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, y| x.name.downcase <=> y.name.downcase} %>
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
+ 1.6.2
@@ -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.
@@ -21,7 +21,10 @@ module CollectiveIdea #:nodoc:
21
21
 
22
22
  # Update cached_level attribute
23
23
  def update_depth
24
- self.update_attribute(:depth, level)
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
@@ -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,y| x.name.mb_chars.downcase <=> y.name.mb_chars.downcase}
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
- class_or_item = class_or_item.roots if class_or_item.is_a?(Class)
66
- items = Array(class_or_item)
67
- result = []
68
- items.sort_by(&sort_proc).each do |item|
69
- hash = item.self_and_descendants.arrange
70
- result += build_node(hash, sort_proc, mover, level){|x, lvl| yield(x, lvl)}
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 << [yield(node, level.to_i), node.id]
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?
@@ -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.1"
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-11}
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 = [
@@ -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(&:name)){|i, level| "#{'-' * level} #{i.name}" }
52
+ sorted_nested_set_options(Category, lambda{|x| x.name }){|i, level| "#{'-' * level} #{i.name}" }
53
53
  end
54
54
 
55
55
  end
@@ -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
@@ -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 test_left_column_name
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
- - 1
9
- version: 1.6.1
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-11 00:00:00 +03:00
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: -134095791
156
+ hash: 754987949
157
157
  segments:
158
158
  - 0
159
159
  version: "0"