nested_set 1.6.4 → 1.6.5

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.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.6.4
1
+ 1.6.5
@@ -25,6 +25,7 @@ module CollectiveIdea #:nodoc:
25
25
  module SingletonMethods
26
26
  # Configuration options are:
27
27
  #
28
+ # * +:primary_key_column+ - specifies the column name to use for keeping the position integer (default: id)
28
29
  # * +:parent_column+ - specifies the column name to use for keeping the position integer (default: parent_id)
29
30
  # * +:left_column+ - column name for left boundry data, default "lft"
30
31
  # * +:right_column+ - column name for right boundry data, default "rgt"
@@ -43,6 +44,7 @@ module CollectiveIdea #:nodoc:
43
44
  # to acts_as_nested_set models
44
45
  def acts_as_nested_set(options = {})
45
46
  options = {
47
+ :primary_key_column => self.primary_key,
46
48
  :parent_column => 'parent_id',
47
49
  :left_column => 'lft',
48
50
  :right_column => 'rgt',
@@ -54,8 +56,8 @@ module CollectiveIdea #:nodoc:
54
56
  options[:scope] = "#{options[:scope]}_id".intern
55
57
  end
56
58
 
57
- write_inheritable_attribute :acts_as_nested_set_options, options
58
- class_inheritable_reader :acts_as_nested_set_options
59
+ class_attribute :acts_as_nested_set_options
60
+ self.acts_as_nested_set_options = options
59
61
 
60
62
  unless self.is_a?(ClassMethods)
61
63
  include Comparable
@@ -142,7 +144,8 @@ module CollectiveIdea #:nodoc:
142
144
  arranged = ActiveSupport::OrderedHash.new
143
145
  insertion_points = [arranged]
144
146
  depth = 0
145
- order(quoted_left_column_name).each_with_level do |node, level|
147
+ order("#{quoted_table_name}.#{quoted_left_column_name}").each_with_level do |node, level|
148
+ next if level > depth && insertion_points.last.keys.last && node.parent_id != insertion_points.last.keys.last.id
146
149
  insertion_points.push insertion_points.last.values.last if level > depth
147
150
  (depth - level).times { insertion_points.pop } if level < depth
148
151
  insertion_points.last.merge! node => ActiveSupport::OrderedHash.new
@@ -175,17 +178,18 @@ module CollectiveIdea #:nodoc:
175
178
  end.push(nil).join(", ")
176
179
  [quoted_left_column_name, quoted_right_column_name].all? do |column|
177
180
  # No duplicates
178
- first(
181
+ unscoped.first(
179
182
  :select => "#{scope_string}#{column}, COUNT(#{column})",
180
- :group => "#{scope_string}#{column}
181
- HAVING COUNT(#{column}) > 1").nil?
183
+ :group => "#{scope_string}#{column}",
184
+ :having => "COUNT(#{column}) > 1"
185
+ ).nil?
182
186
  end
183
187
  end
184
188
 
185
189
  # Wrapper for each_root_valid? that can deal with scope.
186
190
  def all_roots_valid?
187
191
  if acts_as_nested_set_options[:scope]
188
- roots.group(scope_column_names).group_by{|record| scope_column_names.collect{|col| record.send(col.to_sym)}}.all? do |scope, grouped_roots|
192
+ roots.group_by{|record| scope_column_names.collect{|col| record.send(col.to_sym)}}.all? do |scope, grouped_roots|
189
193
  each_root_valid?(grouped_roots)
190
194
  end
191
195
  else
@@ -252,6 +256,14 @@ module CollectiveIdea #:nodoc:
252
256
  end
253
257
  end
254
258
 
259
+ def map_with_level(objects = nil)
260
+ result = []
261
+ each_with_level objects do |object, level|
262
+ result << yield(object, level)
263
+ end
264
+ result
265
+ end
266
+
255
267
  def before_move(*args, &block)
256
268
  set_callback :move, :before, *args, &block
257
269
  end
@@ -283,7 +295,7 @@ module CollectiveIdea #:nodoc:
283
295
  end
284
296
 
285
297
  def order_for_rebuild
286
- "#{quoted_left_column_name}, #{quoted_right_column_name}, id"
298
+ "#{quoted_left_column_name}, #{quoted_right_column_name}, #{primary_key_column_name}"
287
299
  end
288
300
 
289
301
  end
@@ -310,6 +322,10 @@ module CollectiveIdea #:nodoc:
310
322
  acts_as_nested_set_options[:depth_column]
311
323
  end
312
324
 
325
+ def primary_key_column_name
326
+ acts_as_nested_set_options[:primary_key_column]
327
+ end
328
+
313
329
  def quoted_left_column_name
314
330
  connection.quote_column_name(left_column_name)
315
331
  end
@@ -383,6 +399,11 @@ module CollectiveIdea #:nodoc:
383
399
  self_and_ancestors.first
384
400
  end
385
401
 
402
+ # Returns the array of all children and self
403
+ def self_and_children
404
+ nested_set_scope.scoped.where("#{q_parent} = ? or id = ?", id, id)
405
+ end
406
+
386
407
  # Returns the array of all parents and self
387
408
  def self_and_ancestors
388
409
  nested_set_scope.scoped.where("#{q_left} <= ? AND #{q_right} >= ?", left, right)
@@ -496,8 +517,8 @@ module CollectiveIdea #:nodoc:
496
517
  end
497
518
 
498
519
  def to_text
499
- self_and_descendants.map do |node|
500
- "#{'*'*(node.level+1)} #{node.id} #{node.to_s} (#{node.parent_id}, #{node.left}, #{node.right})"
520
+ self.class.map_with_level(self_and_descendants) do |node,level|
521
+ "#{'*'*(level+1)} #{node.id} #{node.to_s} (#{node.parent_id}, #{node.left}, #{node.right})"
501
522
  end.join("\n")
502
523
  end
503
524
 
@@ -511,6 +532,10 @@ module CollectiveIdea #:nodoc:
511
532
  "#{self.class.quoted_table_name}.#{quoted_right_column_name}"
512
533
  end
513
534
 
535
+ def q_parent
536
+ "#{self.class.quoted_table_name}.#{quoted_parent_column_name}"
537
+ end
538
+
514
539
  def without_self(scope)
515
540
  scope.where("#{self.class.quoted_table_name}.#{self.class.primary_key} != ?", self)
516
541
  end
@@ -519,8 +544,8 @@ module CollectiveIdea #:nodoc:
519
544
  # the base ActiveRecord class, using the :scope declared in the acts_as_nested_set
520
545
  # declaration.
521
546
  def nested_set_scope
522
- conditions = Array(acts_as_nested_set_options[:scope]).inject({}) do |conditions, attr|
523
- conditions.merge attr => self[attr]
547
+ conditions = Array(acts_as_nested_set_options[:scope]).inject({}) do |cnd, attr|
548
+ cnd.merge attr => self[attr]
524
549
  end
525
550
 
526
551
  self.class.base_class.order(q_left).where(conditions)
@@ -551,6 +576,7 @@ module CollectiveIdea #:nodoc:
551
576
  # back to the left so the counts still work.
552
577
  def destroy_descendants
553
578
  return if right.nil? || left.nil? || skip_before_destroy
579
+ reload_nested_set
554
580
 
555
581
  self.class.base_class.transaction do
556
582
  if acts_as_nested_set_options[:dependent] == :destroy
@@ -623,6 +649,13 @@ module CollectiveIdea #:nodoc:
623
649
  # so sorting puts both the intervals and their boundaries in order
624
650
  a, b, c, d = [self[left_column_name], self[right_column_name], bound, other_bound].sort
625
651
 
652
+ # select the rows in the model between a and d, and apply a lock
653
+ self.class.base_class.find(:all,
654
+ :select => primary_key_column_name,
655
+ :conditions => ["#{quoted_left_column_name} >= :a and #{quoted_right_column_name} <= :d", {:a => a, :d => d}],
656
+ :lock => true
657
+ )
658
+
626
659
  new_parent = case position
627
660
  when :child; target.id
628
661
  when :root; nil
@@ -11,9 +11,13 @@ module CollectiveIdea #:nodoc:
11
11
  # You can pass a block receiving an item and returning the string displayed in the select.
12
12
  #
13
13
  # == Params
14
- # * +class_or_item+ - Class name or top level times
15
- # * +mover+ - The item that is being move, used to exlude impossible moves
16
- # * +&block+ - a block that will be used to display: { |item| ... item.name }
14
+ # * +class_or_items+ - Class name or top level items
15
+ # * +mover+ - The item that is being move, used to exclude impossible moves
16
+ # * +options+ - hash of additional options
17
+ # * +&block+ - a block that will be used to display: { |item| ... item.name }
18
+ #
19
+ # == Options
20
+ # * +include_root+ - Include root object(s) in output. Default: true
17
21
  #
18
22
  # == Usage
19
23
  #
@@ -21,12 +25,23 @@ module CollectiveIdea #:nodoc:
21
25
  # "#{'–' * level} #{i.name}"
22
26
  # }) %>
23
27
  #
24
- def nested_set_options(class_or_item, mover = nil)
25
- class_or_item = class_or_item.roots if class_or_item.is_a?(Class)
26
- items = Array(class_or_item)
28
+ def nested_set_options(class_or_items, mover = nil, options = {})
29
+ items = case
30
+ when class_or_items.is_a?(Class)
31
+ class_or_items.roots
32
+ when class_or_items.is_a?(Array)
33
+ class_or_items
34
+ else
35
+ [class_or_items]
36
+ end
37
+
38
+ options.assert_valid_keys :include_root
39
+ options.reverse_merge! :include_root => true
40
+
27
41
  result = []
28
42
  items.each do |item|
29
- item.self_and_descendants.each_with_level do |i, level|
43
+ objects = options[:include_root] ? item.self_and_descendants : item.descendants
44
+ objects.each_with_level do |i, level|
30
45
  if mover.nil? || mover.new_record? || mover.move_possible?(i)
31
46
  result.push([yield(i, level), i.id])
32
47
  end
@@ -8,11 +8,11 @@ module CollectiveIdea
8
8
  class Railtie < ::Rails::Railtie
9
9
  config.before_initialize do
10
10
  ActiveSupport.on_load :active_record do
11
- ActiveRecord::Base.send(:include, CollectiveIdea::Acts::NestedSet::Base)
11
+ include CollectiveIdea::Acts::NestedSet::Base
12
12
  end
13
13
 
14
14
  ActiveSupport.on_load :action_view do
15
- ActionView::Base.send(:include, CollectiveIdea::Acts::NestedSet::Helper)
15
+ include CollectiveIdea::Acts::NestedSet::Helper
16
16
  end
17
17
  end
18
18
 
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.4"
8
+ s.version = "1.6.5"
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{2011-02-10}
12
+ s.date = %q{2011-05-24}
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 = [
@@ -45,7 +45,7 @@ Gem::Specification.new do |s|
45
45
  ]
46
46
  s.homepage = %q{http://github.com/skyeagle/nested_set}
47
47
  s.require_paths = ["lib"]
48
- s.rubygems_version = %q{1.3.7}
48
+ s.rubygems_version = %q{1.6.2}
49
49
  s.summary = %q{An awesome nested set implementation for Active Record}
50
50
  s.test_files = [
51
51
  "test/benchmarks.rb",
@@ -57,7 +57,6 @@ Gem::Specification.new do |s|
57
57
  ]
58
58
 
59
59
  if s.respond_to? :specification_version then
60
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
61
60
  s.specification_version = 3
62
61
 
63
62
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
@@ -5,12 +5,22 @@ class Category < ActiveRecord::Base
5
5
  name
6
6
  end
7
7
 
8
- def recurse &block
8
+ def recurse(&block)
9
9
  block.call self, lambda{
10
10
  self.children.each do |child|
11
- child.recurse &block
11
+ child.recurse(&block)
12
12
  end
13
13
  }
14
14
  end
15
15
 
16
16
  end
17
+
18
+ class Category_NoToArray < Category
19
+ def to_a
20
+ raise 'to_a called'
21
+ end
22
+ end
23
+
24
+ class Category_DefaultScope < Category
25
+ default_scope order('categories.id ASC')
26
+ end
@@ -19,6 +19,19 @@ class HelperTest < ActionView::TestCase
19
19
  assert_equal expected, actual
20
20
  end
21
21
 
22
+ def test_nested_set_options_without_root
23
+ expected = [
24
+ [" Child 1", 2],
25
+ [' Child 2', 3],
26
+ ['- Child 2.1', 4],
27
+ [' Child 3', 5]
28
+ ]
29
+ actual = nested_set_options(categories(:top_level), nil, :include_root => false) do |c, level|
30
+ "#{'-' * level} #{c.name}"
31
+ end
32
+ assert_equal expected, actual
33
+ end
34
+
22
35
  def test_nested_set_options_with_mover
23
36
  expected = [
24
37
  [" Top Level", 1],
@@ -100,4 +113,15 @@ class HelperTest < ActionView::TestCase
100
113
  assert_equal html, "<ul><li>Top Level 2</li><li>Top Level</li><ul><li>Child 3</li><li>Child 2</li><ul><li>Child 2.1</li></ul><li>Child 1</li></ul></ul>"
101
114
  end
102
115
 
116
+ def test_nested_set_options_does_not_call_to_a
117
+ expected = [
118
+ ['Child 2', 3],
119
+ ['Child 2.1', 4]
120
+ ]
121
+ actual = nested_set_options Category_NoToArray.find(3) do |c|
122
+ c.name
123
+ end
124
+ assert_equal expected, actual
125
+ end
126
+
103
127
  end
@@ -130,10 +130,10 @@ class NestedSetTest < ActiveSupport::TestCase
130
130
  def test_leaves_class_method
131
131
  assert_equal Category.find(:all, :conditions => "#{Category.right_column_name} - #{Category.left_column_name} = 1"), Category.leaves
132
132
  assert_equal Category.leaves.count, 4
133
- assert (Category.leaves.include? categories(:child_1))
134
- assert (Category.leaves.include? categories(:child_2_1))
135
- assert (Category.leaves.include? categories(:child_3))
136
- assert (Category.leaves.include? categories(:top_level_2))
133
+ assert Category.leaves.include?(categories(:child_1))
134
+ assert Category.leaves.include?(categories(:child_2_1))
135
+ assert Category.leaves.include?(categories(:child_3))
136
+ assert Category.leaves.include?(categories(:top_level_2))
137
137
  end
138
138
 
139
139
  def test_leaf
@@ -147,11 +147,16 @@ class NestedSetTest < ActiveSupport::TestCase
147
147
  assert !Category.new.leaf?
148
148
  end
149
149
 
150
-
151
150
  def test_parent
152
151
  assert_equal categories(:child_2), categories(:child_2_1).parent
153
152
  end
154
153
 
154
+ def test_self_and_chilren
155
+ node = categories(:top_level)
156
+ self_and_children = [node, categories(:child_1), categories(:child_2), categories(:child_3)]
157
+ assert_equal self_and_children, node.self_and_children
158
+ end
159
+
155
160
  def test_self_and_ancestors
156
161
  child = categories(:child_2_1)
157
162
  self_and_ancestors = [categories(:top_level), categories(:child_2), child]
@@ -675,6 +680,12 @@ class NestedSetTest < ActiveSupport::TestCase
675
680
  assert Category.valid?
676
681
  end
677
682
 
683
+ def test_destroy_on_multiple_records_without_reload_does_not_invalidate
684
+ Category.acts_as_nested_set_options[:dependent] = :destroy
685
+ [categories(:child_1), categories(:child_2)].each(&:destroy)
686
+ assert Category.valid?
687
+ end
688
+
678
689
  def test_assigning_parent_id_on_create
679
690
  category = Category.create!(:name => "Child", :parent_id => categories(:child_2).id)
680
691
  assert_equal categories(:child_2), category.parent
@@ -756,6 +767,10 @@ class NestedSetTest < ActiveSupport::TestCase
756
767
  end
757
768
  end
758
769
 
770
+ def test_valid_with_default_scope
771
+ assert Category_DefaultScope.valid?
772
+ end
773
+
759
774
  def test_each_with_level
760
775
  levels = [
761
776
  [0, "Top Level"],
@@ -794,6 +809,20 @@ class NestedSetTest < ActiveSupport::TestCase
794
809
  check_scoped_structure(Category.root.self_and_descendants, levels)
795
810
  end
796
811
 
812
+ def test_map_with_level
813
+ expected = [
814
+ [0, "Top Level"],
815
+ [1, "Child 1"],
816
+ [1, "Child 2"],
817
+ [2, "Child 2.1"],
818
+ [1, "Child 3" ]
819
+ ]
820
+ actual = Category.map_with_level Category.root.self_and_descendants do |i, level|
821
+ [level, i.name]
822
+ end
823
+ assert_equal expected, actual
824
+ end
825
+
797
826
  def test_model_with_attr_accessible
798
827
  model = Class.new(ActiveRecord::Base)
799
828
  model.set_table_name 'categories'
metadata CHANGED
@@ -1,118 +1,91 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: nested_set
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 1
7
- - 6
8
- - 4
9
- version: 1.6.4
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.6.5
5
+ prerelease:
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - Brandon Keepers
13
9
  - Daniel Morrison
14
10
  autorequire:
15
11
  bindir: bin
16
12
  cert_chain: []
17
-
18
- date: 2011-02-10 00:00:00 +03:00
13
+ date: 2011-05-24 00:00:00.000000000 +04:00
19
14
  default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
22
17
  name: railties
23
- requirement: &id001 !ruby/object:Gem::Requirement
18
+ requirement: &11153540 !ruby/object:Gem::Requirement
24
19
  none: false
25
- requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- segments:
29
- - 3
30
- - 0
31
- - 0
20
+ requirements:
21
+ - - ! '>='
22
+ - !ruby/object:Gem::Version
32
23
  version: 3.0.0
33
24
  type: :runtime
34
25
  prerelease: false
35
- version_requirements: *id001
36
- - !ruby/object:Gem::Dependency
26
+ version_requirements: *11153540
27
+ - !ruby/object:Gem::Dependency
37
28
  name: activerecord
38
- requirement: &id002 !ruby/object:Gem::Requirement
29
+ requirement: &11152400 !ruby/object:Gem::Requirement
39
30
  none: false
40
- requirements:
41
- - - ">="
42
- - !ruby/object:Gem::Version
43
- segments:
44
- - 3
45
- - 0
46
- - 0
31
+ requirements:
32
+ - - ! '>='
33
+ - !ruby/object:Gem::Version
47
34
  version: 3.0.0
48
35
  type: :runtime
49
36
  prerelease: false
50
- version_requirements: *id002
51
- - !ruby/object:Gem::Dependency
37
+ version_requirements: *11152400
38
+ - !ruby/object:Gem::Dependency
52
39
  name: sqlite3-ruby
53
- requirement: &id003 !ruby/object:Gem::Requirement
40
+ requirement: &11151640 !ruby/object:Gem::Requirement
54
41
  none: false
55
- requirements:
56
- - - ">="
57
- - !ruby/object:Gem::Version
58
- segments:
59
- - 0
60
- version: "0"
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
61
46
  type: :development
62
47
  prerelease: false
63
- version_requirements: *id003
64
- - !ruby/object:Gem::Dependency
48
+ version_requirements: *11151640
49
+ - !ruby/object:Gem::Dependency
65
50
  name: actionpack
66
- requirement: &id004 !ruby/object:Gem::Requirement
51
+ requirement: &11148600 !ruby/object:Gem::Requirement
67
52
  none: false
68
- requirements:
69
- - - ">="
70
- - !ruby/object:Gem::Version
71
- segments:
72
- - 3
73
- - 0
74
- - 0
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
75
56
  version: 3.0.0
76
57
  type: :development
77
58
  prerelease: false
78
- version_requirements: *id004
79
- - !ruby/object:Gem::Dependency
59
+ version_requirements: *11148600
60
+ - !ruby/object:Gem::Dependency
80
61
  name: bench_press
81
- requirement: &id005 !ruby/object:Gem::Requirement
62
+ requirement: &11147700 !ruby/object:Gem::Requirement
82
63
  none: false
83
- requirements:
84
- - - ">="
85
- - !ruby/object:Gem::Version
86
- segments:
87
- - 0
88
- - 3
89
- - 1
64
+ requirements:
65
+ - - ! '>='
66
+ - !ruby/object:Gem::Version
90
67
  version: 0.3.1
91
68
  type: :development
92
69
  prerelease: false
93
- version_requirements: *id005
94
- - !ruby/object:Gem::Dependency
70
+ version_requirements: *11147700
71
+ - !ruby/object:Gem::Dependency
95
72
  name: jeweler
96
- requirement: &id006 !ruby/object:Gem::Requirement
73
+ requirement: &11146880 !ruby/object:Gem::Requirement
97
74
  none: false
98
- requirements:
99
- - - ">="
100
- - !ruby/object:Gem::Version
101
- segments:
102
- - 0
103
- version: "0"
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
104
79
  type: :development
105
80
  prerelease: false
106
- version_requirements: *id006
81
+ version_requirements: *11146880
107
82
  description: An awesome nested set implementation for Active Record
108
83
  email: info@collectiveidea.com
109
84
  executables: []
110
-
111
85
  extensions: []
112
-
113
- extra_rdoc_files:
86
+ extra_rdoc_files:
114
87
  - README.md
115
- files:
88
+ files:
116
89
  - .autotest
117
90
  - Gemfile
118
91
  - Gemfile.lock
@@ -142,37 +115,32 @@ files:
142
115
  has_rdoc: true
143
116
  homepage: http://github.com/skyeagle/nested_set
144
117
  licenses: []
145
-
146
118
  post_install_message:
147
119
  rdoc_options: []
148
-
149
- require_paths:
120
+ require_paths:
150
121
  - lib
151
- required_ruby_version: !ruby/object:Gem::Requirement
122
+ required_ruby_version: !ruby/object:Gem::Requirement
152
123
  none: false
153
- requirements:
154
- - - ">="
155
- - !ruby/object:Gem::Version
156
- hash: 462466689
157
- segments:
124
+ requirements:
125
+ - - ! '>='
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ segments:
158
129
  - 0
159
- version: "0"
160
- required_rubygems_version: !ruby/object:Gem::Requirement
130
+ hash: -1622325140072455651
131
+ required_rubygems_version: !ruby/object:Gem::Requirement
161
132
  none: false
162
- requirements:
163
- - - ">="
164
- - !ruby/object:Gem::Version
165
- segments:
166
- - 0
167
- version: "0"
133
+ requirements:
134
+ - - ! '>='
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
168
137
  requirements: []
169
-
170
138
  rubyforge_project:
171
- rubygems_version: 1.3.7
139
+ rubygems_version: 1.6.2
172
140
  signing_key:
173
141
  specification_version: 3
174
142
  summary: An awesome nested set implementation for Active Record
175
- test_files:
143
+ test_files:
176
144
  - test/benchmarks.rb
177
145
  - test/db/schema.rb
178
146
  - test/fixtures/category.rb