acts_as_tree 0.1.1 → 0.2.0

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/.gitignore CHANGED
@@ -1,6 +1,5 @@
1
- *.sw?
2
- .DS_Store
3
- coverage
4
- doc
5
- rdoc
6
- pkg
1
+ *.gem
2
+ .bundle
3
+ pkg/*
4
+ .rvmrc
5
+ Gemfile.lock
data/.travis.yml ADDED
@@ -0,0 +1,9 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
5
+ - 1.9.3
6
+ - rbx-18mode
7
+ - rbx-19mode
8
+ - ree
9
+ - ruby-head
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source :rubygems
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem 'rake'
7
+ end
data/README.md ADDED
@@ -0,0 +1,28 @@
1
+ [![Build Status](https://secure.travis-ci.org/amerine/acts_as_tree.png?branch=master)](http://travis-ci.org/amerine/acts_as_tree)
2
+
3
+ # ActsAsTree
4
+
5
+ ## Notes
6
+ Specify this `acts_as` extension if you want to model a tree structure by providing a parent association and a children association. This requires that you have a foreign key column, which by default is called `parent_id`.
7
+
8
+ class Category < ActiveRecord::Base
9
+ acts_as_tree :order => "name"
10
+ end
11
+
12
+ Example:
13
+ root
14
+ \_ child1
15
+ \_ subchild1
16
+ \_ subchild2
17
+
18
+ root = Category.create("name" => "root")
19
+ child1 = root.children.create("name" => "child1")
20
+ subchild1 = child1.children.create("name" => "subchild1")
21
+
22
+ root.parent # => nil
23
+ child1.parent # => root
24
+ root.children # => [child1]
25
+ root.children.first.children.first # => subchild1
26
+
27
+
28
+ Copyright (c) 2007 David Heinemeier Hansson, released under the MIT license
data/Rakefile CHANGED
@@ -1,54 +1,21 @@
1
- require 'rubygems'
2
- require 'rake'
1
+ require 'bundler/gem_tasks'
3
2
 
4
- begin
5
- require 'jeweler'
6
- Jeweler::Tasks.new do |gem|
7
- gem.name = "acts_as_tree"
8
- gem.summary = %Q{Gem version of acts_as_tree Rails plugin.}
9
- gem.description = %Q{Specify this acts_as extension if you want to model a tree structure by providing a parent association and a children association.}
10
- gem.email = "erik.dahlstrand@gmail.com"
11
- gem.homepage = "http://github.com/erdah/acts_as_tree"
12
- gem.authors = ["Erik Dahlstrand", "Rails Core"]
13
- end
14
- rescue LoadError
15
- puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
3
+ desc "Run the tests."
4
+ task :test do
5
+ $: << "lib" << "test"
6
+ Dir["test/*_test.rb"].each { |f| require f[5..-4] }
16
7
  end
17
8
 
18
- require 'rake/testtask'
19
- Rake::TestTask.new(:test) do |test|
20
- test.libs << 'lib' << 'test'
21
- test.pattern = 'test/**/*_test.rb'
22
- test.verbose = true
23
- end
24
-
25
- begin
26
- require 'rcov/rcovtask'
27
- Rcov::RcovTask.new do |test|
28
- test.libs << 'test'
29
- test.pattern = 'test/**/*_test.rb'
30
- test.verbose = true
31
- end
32
- rescue LoadError
33
- task :rcov do
34
- abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
35
- end
36
- end
37
-
38
- task :test => :check_dependencies
39
-
40
9
  task :default => :test
41
10
 
42
- require 'rake/rdoctask'
43
- Rake::RDocTask.new do |rdoc|
44
- if File.exist?('VERSION')
45
- version = File.read('VERSION')
46
- else
47
- version = ""
48
- end
11
+ # Run the rdoc task to generate rdocs for this gem
12
+ require 'rdoc/task'
13
+ RDoc::Task.new do |rdoc|
14
+ require "acts_as_tree/version"
15
+ version = ActiveRecord::Acts::Tree::VERSION
49
16
 
50
17
  rdoc.rdoc_dir = 'rdoc'
51
- rdoc.title = "acts_as_tree #{version}"
18
+ rdoc.title = "acts_as_tree-rails3 #{version}"
52
19
  rdoc.rdoc_files.include('README*')
53
20
  rdoc.rdoc_files.include('lib/**/*.rb')
54
21
  end
data/acts_as_tree.gemspec CHANGED
@@ -1,47 +1,27 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
1
  # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "acts_as_tree/version"
5
4
 
6
5
  Gem::Specification.new do |s|
7
- s.name = %q{acts_as_tree}
8
- s.version = "0.1.1"
9
-
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Erik Dahlstrand", "Rails Core"]
12
- s.date = %q{2010-02-04}
6
+ s.name = "acts_as_tree"
7
+ s.version = ActiveRecord::Acts::Tree::VERSION
8
+ s.authors = ["Erik Dahlstrand", "Rails Core", "Mark Turner", "Swanand Pagnis"]
9
+ s.email = ["erik.dahlstrand@gmail.com", "mark@amerine.net", "swanand.pagnis@gmail.com"]
10
+ s.homepage = "https://github.com/amerine/acts_as_tree"
11
+ s.summary = %q{Provides a simple tree behaviour to active_record mdoels.}
13
12
  s.description = %q{Specify this acts_as extension if you want to model a tree structure by providing a parent association and a children association.}
14
- s.email = %q{erik.dahlstrand@gmail.com}
15
- s.extra_rdoc_files = [
16
- "README.rdoc"
17
- ]
18
- s.files = [
19
- ".document",
20
- ".gitignore",
21
- "README.rdoc",
22
- "Rakefile",
23
- "VERSION",
24
- "acts_as_tree.gemspec",
25
- "lib/acts_as_tree.rb",
26
- "test/acts_as_tree_test.rb"
27
- ]
28
- s.homepage = %q{http://github.com/erdah/acts_as_tree}
29
- s.rdoc_options = ["--charset=UTF-8"]
30
- s.require_paths = ["lib"]
31
- s.rubygems_version = %q{1.3.5}
32
- s.summary = %q{Gem version of acts_as_tree Rails plugin.}
33
- s.test_files = [
34
- "test/acts_as_tree_test.rb"
35
- ]
36
13
 
37
- if s.respond_to? :specification_version then
38
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
39
- s.specification_version = 3
14
+ s.rubyforge_project = "acts_as_tree"
40
15
 
41
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
42
- else
43
- end
44
- else
45
- end
46
- end
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+ s.rdoc_options = ["--charset=UTF-8"]
47
21
 
22
+ # Dependencies (installed via 'bundle install')...
23
+ s.add_development_dependency("bundler", [">= 1.0.0"])
24
+ s.add_development_dependency("activerecord", [">= 1.15.4.7794"])
25
+ s.add_development_dependency("rdoc")
26
+ s.add_development_dependency("sqlite3")
27
+ end
data/init.rb ADDED
@@ -0,0 +1,2 @@
1
+ $:.unshift "#{File.dirname(__FILE__)}/lib"
2
+ require 'acts_as_tree'
@@ -0,0 +1,142 @@
1
+ module ActiveRecord
2
+ module Acts #:nodoc:
3
+ module Tree #:nodoc:
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
7
+
8
+ # Specify this +acts_as+ extension if you want to model a tree structure
9
+ # by providing a parent association and a children association. This
10
+ # requires that you have a foreign key column, which by default is called
11
+ # +parent_id+.
12
+ #
13
+ # class Category < ActiveRecord::Base
14
+ # acts_as_tree :order => "name"
15
+ # end
16
+ #
17
+ # Example:
18
+ # root
19
+ # \_ child1
20
+ # \_ subchild1
21
+ # \_ subchild2
22
+ #
23
+ # root = Category.create("name" => "root")
24
+ # child1 = root.children.create("name" => "child1")
25
+ # subchild1 = child1.children.create("name" => "subchild1")
26
+ #
27
+ # root.parent # => nil
28
+ # child1.parent # => root
29
+ # root.children # => [child1]
30
+ # root.children.first.children.first # => subchild1
31
+ #
32
+ # In addition to the parent and children associations, the following
33
+ # instance methods are added to the class after calling
34
+ # <tt>acts_as_tree</tt>:
35
+ # * <tt>siblings</tt> - Returns all the children of the parent, excluding
36
+ # the current node (<tt>[subchild2]</tt> when called
37
+ # on <tt>subchild1</tt>)
38
+ # * <tt>self_and_siblings</tt> - Returns all the children of the parent,
39
+ # including the current node (<tt>[subchild1, subchild2]</tt>
40
+ # when called on <tt>subchild1</tt>)
41
+ # * <tt>ancestors</tt> - Returns all the ancestors of the current node
42
+ # (<tt>[child1, root]</tt> when called on <tt>subchild2</tt>)
43
+ # * <tt>root</tt> - Returns the root of the current node (<tt>root</tt>
44
+ # when called on <tt>subchild2</tt>)
45
+ module ClassMethods
46
+ # Configuration options are:
47
+ #
48
+ # * <tt>foreign_key</tt> - specifies the column name to use for tracking
49
+ # of the tree (default: +parent_id+)
50
+ # * <tt>order</tt> - makes it possible to sort the children according to
51
+ # this SQL snippet.
52
+ # * <tt>counter_cache</tt> - keeps a count in a +children_count+ column
53
+ # if set to +true+ (default: +false+).
54
+ def acts_as_tree(options = {})
55
+ configuration = {
56
+ :foreign_key => "parent_id",
57
+ :order => nil,
58
+ :counter_cache => nil,
59
+ :dependent => :destroy
60
+ }
61
+
62
+ configuration.update(options) if options.is_a?(Hash)
63
+
64
+ belongs_to :parent, :class_name => name,
65
+ :foreign_key => configuration[:foreign_key],
66
+ :counter_cache => configuration[:counter_cache],
67
+ :inverse_of => :children
68
+
69
+ has_many :children, :class_name => name,
70
+ :foreign_key => configuration[:foreign_key],
71
+ :order => configuration[:order],
72
+ :dependent => configuration[:dependent],
73
+ :inverse_of => :parent
74
+
75
+ class_eval <<-EOV
76
+ include ActiveRecord::Acts::Tree::InstanceMethods
77
+
78
+ after_update :update_parents_counter_cache
79
+
80
+ def self.roots
81
+ find(:all, :conditions => "#{configuration[:foreign_key]} IS NULL",
82
+ :order => #{configuration[:order].nil? ? "nil" : %Q{"#{configuration[:order]}"}})
83
+ end
84
+
85
+ def self.root
86
+ find(:first, :conditions => "#{configuration[:foreign_key]} IS NULL",
87
+ :order => #{configuration[:order].nil? ? "nil" : %Q{"#{configuration[:order]}"}})
88
+ end
89
+ EOV
90
+ end
91
+ end
92
+
93
+ module InstanceMethods
94
+ # Returns list of ancestors, starting from parent until root.
95
+ #
96
+ # subchild1.ancestors # => [child1, root]
97
+ def ancestors
98
+ node, nodes = self, []
99
+ nodes << node = node.parent while node.parent
100
+ nodes
101
+ end
102
+
103
+ # Returns the root node of the tree.
104
+ def root
105
+ node = self
106
+ node = node.parent while node.parent
107
+ node
108
+ end
109
+
110
+ # Returns all siblings of the current node.
111
+ #
112
+ # subchild1.siblings # => [subchild2]
113
+ def siblings
114
+ self_and_siblings - [self]
115
+ end
116
+
117
+ # Returns all siblings and a reference to the current node.
118
+ #
119
+ # subchild1.self_and_siblings # => [subchild1, subchild2]
120
+ def self_and_siblings
121
+ parent ? parent.children : self.class.roots
122
+ end
123
+
124
+ # Returns children (without subchildren) and current node itself.
125
+ #
126
+ # root.self_and_children # => [root, child1]
127
+ def self_and_children
128
+ [self] + self.children
129
+ end
130
+
131
+ private
132
+
133
+ def update_parents_counter_cache
134
+ if self.respond_to?(:children_count) && parent_id_changed?
135
+ self.class.decrement_counter(:children_count, parent_id_was)
136
+ self.class.increment_counter(:children_count, parent_id)
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,7 @@
1
+ module ActiveRecord
2
+ module Acts
3
+ module Tree
4
+ VERSION = "0.2.0"
5
+ end
6
+ end
7
+ end
data/lib/acts_as_tree.rb CHANGED
@@ -1,96 +1,3 @@
1
- require 'active_record/base'
2
-
3
- module ActsAsTree
4
- def self.included(base)
5
- base.extend(ClassMethods)
6
- end
7
-
8
- # Specify this +acts_as+ extension if you want to model a tree structure by providing a parent association and a children
9
- # association. This requires that you have a foreign key column, which by default is called +parent_id+.
10
- #
11
- # class Category < ActiveRecord::Base
12
- # acts_as_tree :order => "name"
13
- # end
14
- #
15
- # Example:
16
- # root
17
- # \_ child1
18
- # \_ subchild1
19
- # \_ subchild2
20
- #
21
- # root = Category.create("name" => "root")
22
- # child1 = root.children.create("name" => "child1")
23
- # subchild1 = child1.children.create("name" => "subchild1")
24
- #
25
- # root.parent # => nil
26
- # child1.parent # => root
27
- # root.children # => [child1]
28
- # root.children.first.children.first # => subchild1
29
- #
30
- # In addition to the parent and children associations, the following instance methods are added to the class
31
- # after calling <tt>acts_as_tree</tt>:
32
- # * <tt>siblings</tt> - Returns all the children of the parent, excluding the current node (<tt>[subchild2]</tt> when called on <tt>subchild1</tt>)
33
- # * <tt>self_and_siblings</tt> - Returns all the children of the parent, including the current node (<tt>[subchild1, subchild2]</tt> when called on <tt>subchild1</tt>)
34
- # * <tt>ancestors</tt> - Returns all the ancestors of the current node (<tt>[child1, root]</tt> when called on <tt>subchild2</tt>)
35
- # * <tt>root</tt> - Returns the root of the current node (<tt>root</tt> when called on <tt>subchild2</tt>)
36
- module ClassMethods
37
- # Configuration options are:
38
- #
39
- # * <tt>foreign_key</tt> - specifies the column name to use for tracking of the tree (default: +parent_id+)
40
- # * <tt>order</tt> - makes it possible to sort the children according to this SQL snippet.
41
- # * <tt>counter_cache</tt> - keeps a count in a +children_count+ column if set to +true+ (default: +false+).
42
- def acts_as_tree(options = {})
43
- configuration = { :foreign_key => "parent_id", :order => nil, :counter_cache => nil }
44
- configuration.update(options) if options.is_a?(Hash)
45
-
46
- belongs_to :parent, :class_name => name, :foreign_key => configuration[:foreign_key], :counter_cache => configuration[:counter_cache]
47
- has_many :children, :class_name => name, :foreign_key => configuration[:foreign_key], :order => configuration[:order], :dependent => :destroy
48
-
49
- class_eval <<-EOV
50
- include ActsAsTree::InstanceMethods
51
-
52
- def self.roots
53
- find(:all, :conditions => "#{configuration[:foreign_key]} IS NULL", :order => #{configuration[:order].nil? ? "nil" : %Q{"#{configuration[:order]}"}})
54
- end
55
-
56
- def self.root
57
- find(:first, :conditions => "#{configuration[:foreign_key]} IS NULL", :order => #{configuration[:order].nil? ? "nil" : %Q{"#{configuration[:order]}"}})
58
- end
59
- EOV
60
- end
61
- end
62
-
63
- module InstanceMethods
64
- # Returns list of ancestors, starting from parent until root.
65
- #
66
- # subchild1.ancestors # => [child1, root]
67
- def ancestors
68
- node, nodes = self, []
69
- nodes << node = node.parent while node.parent
70
- nodes
71
- end
72
-
73
- # Returns the root node of the tree.
74
- def root
75
- node = self
76
- node = node.parent while node.parent
77
- node
78
- end
79
-
80
- # Returns all siblings of the current node.
81
- #
82
- # subchild1.siblings # => [subchild2]
83
- def siblings
84
- self_and_siblings - [self]
85
- end
86
-
87
- # Returns all siblings and a reference to the current node.
88
- #
89
- # subchild1.self_and_siblings # => [subchild1, subchild2]
90
- def self_and_siblings
91
- parent ? parent.children : self.class.roots
92
- end
93
- end
94
- end
95
-
96
- ActiveRecord::Base.class_eval { include ActsAsTree }
1
+ require 'acts_as_tree/active_record/acts/tree'
2
+ require 'acts_as_tree/version'
3
+ ActiveRecord::Base.class_eval { include ActiveRecord::Acts::Tree }
@@ -1,9 +1,6 @@
1
1
  require 'test/unit'
2
-
3
- require 'rubygems'
4
2
  require 'active_record'
5
-
6
- require "#{File.dirname(__FILE__)}/../lib/acts_as_tree"
3
+ require "#{File.dirname(__FILE__)}/../init"
7
4
 
8
5
  class Test::Unit::TestCase
9
6
  def assert_queries(num = 1)
@@ -29,6 +26,7 @@ def setup_db
29
26
  create_table :mixins do |t|
30
27
  t.column :type, :string
31
28
  t.column :parent_id, :integer
29
+ t.column :children_count, :integer, :default => 0
32
30
  end
33
31
  end
34
32
  end
@@ -42,7 +40,7 @@ end
42
40
  class Mixin < ActiveRecord::Base
43
41
  end
44
42
 
45
- class TreeMixin < Mixin
43
+ class TreeMixin < Mixin
46
44
  acts_as_tree :foreign_key => "parent_id", :order => "id"
47
45
  end
48
46
 
@@ -50,18 +48,27 @@ class TreeMixinWithoutOrder < Mixin
50
48
  acts_as_tree :foreign_key => "parent_id"
51
49
  end
52
50
 
51
+ class TreeMixinNullify < Mixin
52
+ acts_as_tree :foreign_key => "parent_id", :order => "id", :dependent => :nullify
53
+ end
54
+
55
+ class TreeMixinWithCounterCache < Mixin
56
+ acts_as_tree :foreign_key => "parent_id", :order => "id", :counter_cache => :children_count
57
+ end
58
+
53
59
  class RecursivelyCascadedTreeMixin < Mixin
54
60
  acts_as_tree :foreign_key => "parent_id"
55
61
  has_one :first_child, :class_name => 'RecursivelyCascadedTreeMixin', :foreign_key => :parent_id
56
62
  end
57
63
 
58
64
  class TreeTest < Test::Unit::TestCase
59
-
65
+
60
66
  def setup
61
67
  setup_db
62
68
  @root1 = TreeMixin.create!
63
69
  @root_child1 = TreeMixin.create! :parent_id => @root1.id
64
70
  @child1_child = TreeMixin.create! :parent_id => @root_child1.id
71
+ @child1_child_child = TreeMixin.create! :parent_id => @child1_child.id
65
72
  @root_child2 = TreeMixin.create! :parent_id => @root1.id
66
73
  @root2 = TreeMixin.create!
67
74
  @root3 = TreeMixin.create!
@@ -74,7 +81,8 @@ class TreeTest < Test::Unit::TestCase
74
81
  def test_children
75
82
  assert_equal @root1.children, [@root_child1, @root_child2]
76
83
  assert_equal @root_child1.children, [@child1_child]
77
- assert_equal @child1_child.children, []
84
+ assert_equal @child1_child.children, [@child1_child_child]
85
+ assert_equal @child1_child_child.children, []
78
86
  assert_equal @root_child2.children, []
79
87
  end
80
88
 
@@ -85,7 +93,7 @@ class TreeTest < Test::Unit::TestCase
85
93
  end
86
94
 
87
95
  def test_delete
88
- assert_equal 6, TreeMixin.count
96
+ assert_equal 7, TreeMixin.count
89
97
  @root1.destroy
90
98
  assert_equal 2, TreeMixin.count
91
99
  @root2.destroy
@@ -100,7 +108,7 @@ class TreeTest < Test::Unit::TestCase
100
108
 
101
109
  assert_equal @extra.parent, @root1
102
110
 
103
- assert_equal 3, @root1.children.size
111
+ assert_equal 3, @root1.reload.children.count
104
112
  assert @root1.children.include?(@extra)
105
113
  assert @root1.children.include?(@root_child1)
106
114
  assert @root1.children.include?(@root_child2)
@@ -145,12 +153,28 @@ class TreeTest < Test::Unit::TestCase
145
153
  assert_equal [@root_child1, @root_child2], @root_child2.self_and_siblings
146
154
  assert_equal [@root1, @root2, @root3], @root2.self_and_siblings
147
155
  assert_equal [@root1, @root2, @root3], @root3.self_and_siblings
148
- end
156
+ end
157
+
158
+ def test_self_and_children
159
+ assert_equal [@root1, @root_child1, @root_child2], @root1.self_and_children
160
+ assert_equal [@root2], @root2.self_and_children
161
+ end
162
+
163
+ def test_nullify
164
+ root4 = TreeMixinNullify.create!
165
+ root4_child = TreeMixinNullify.create! :parent_id => root4.id
166
+ assert_equal 2, TreeMixinNullify.count
167
+ assert_equal root4.id, root4_child.parent_id
168
+ root4.destroy
169
+ assert_equal 1, TreeMixinNullify.count
170
+ assert_nil root4_child.reload.parent_id
171
+ end
172
+
149
173
  end
150
174
 
151
175
  class TreeTestWithEagerLoading < Test::Unit::TestCase
152
-
153
- def setup
176
+
177
+ def setup
154
178
  teardown_db
155
179
  setup_db
156
180
  @root1 = TreeMixin.create!
@@ -159,9 +183,9 @@ class TreeTestWithEagerLoading < Test::Unit::TestCase
159
183
  @root_child2 = TreeMixin.create! :parent_id => @root1.id
160
184
  @root2 = TreeMixin.create!
161
185
  @root3 = TreeMixin.create!
162
-
186
+
163
187
  @rc1 = RecursivelyCascadedTreeMixin.create!
164
- @rc2 = RecursivelyCascadedTreeMixin.create! :parent_id => @rc1.id
188
+ @rc2 = RecursivelyCascadedTreeMixin.create! :parent_id => @rc1.id
165
189
  @rc3 = RecursivelyCascadedTreeMixin.create! :parent_id => @rc2.id
166
190
  @rc4 = RecursivelyCascadedTreeMixin.create! :parent_id => @rc3.id
167
191
  end
@@ -169,36 +193,36 @@ class TreeTestWithEagerLoading < Test::Unit::TestCase
169
193
  def teardown
170
194
  teardown_db
171
195
  end
172
-
196
+
173
197
  def test_eager_association_loading
174
198
  roots = TreeMixin.find(:all, :include => :children, :conditions => "mixins.parent_id IS NULL", :order => "mixins.id")
175
- assert_equal [@root1, @root2, @root3], roots
199
+ assert_equal [@root1, @root2, @root3], roots
176
200
  assert_no_queries do
177
- assert_equal 2, roots[0].children.size
178
- assert_equal 0, roots[1].children.size
179
- assert_equal 0, roots[2].children.size
180
- end
201
+ assert_equal 2, roots[0].children.count
202
+ assert_equal 0, roots[1].children.count
203
+ assert_equal 0, roots[2].children.count
204
+ end
181
205
  end
182
-
206
+
183
207
  def test_eager_association_loading_with_recursive_cascading_three_levels_has_many
184
208
  root_node = RecursivelyCascadedTreeMixin.find(:first, :include => { :children => { :children => :children } }, :order => 'mixins.id')
185
209
  assert_equal @rc4, assert_no_queries { root_node.children.first.children.first.children.first }
186
210
  end
187
-
211
+
188
212
  def test_eager_association_loading_with_recursive_cascading_three_levels_has_one
189
213
  root_node = RecursivelyCascadedTreeMixin.find(:first, :include => { :first_child => { :first_child => :first_child } }, :order => 'mixins.id')
190
214
  assert_equal @rc4, assert_no_queries { root_node.first_child.first_child.first_child }
191
215
  end
192
-
216
+
193
217
  def test_eager_association_loading_with_recursive_cascading_three_levels_belongs_to
194
218
  leaf_node = RecursivelyCascadedTreeMixin.find(:first, :include => { :parent => { :parent => :parent } }, :order => 'mixins.id DESC')
195
219
  assert_equal @rc1, assert_no_queries { leaf_node.parent.parent.parent }
196
- end
220
+ end
197
221
  end
198
222
 
199
223
  class TreeTestWithoutOrder < Test::Unit::TestCase
200
-
201
- def setup
224
+
225
+ def setup
202
226
  setup_db
203
227
  @root1 = TreeMixinWithoutOrder.create!
204
228
  @root2 = TreeMixinWithoutOrder.create!
@@ -211,8 +235,53 @@ class TreeTestWithoutOrder < Test::Unit::TestCase
211
235
  def test_root
212
236
  assert [@root1, @root2].include?(TreeMixinWithoutOrder.root)
213
237
  end
214
-
238
+
215
239
  def test_roots
216
240
  assert_equal [], [@root1, @root2] - TreeMixinWithoutOrder.roots
217
241
  end
218
- end
242
+ end
243
+
244
+ class UnsavedTreeTest < Test::Unit::TestCase
245
+ def setup
246
+ setup_db
247
+ @root = TreeMixin.new
248
+ @root_child = @root.children.build
249
+ end
250
+
251
+ def teardown
252
+ teardown_db
253
+ end
254
+
255
+ def test_inverse_of
256
+ # We want children to be aware of their parent before saving either
257
+ assert_equal @root, @root_child.parent
258
+ end
259
+ end
260
+
261
+
262
+ class TreeTestWithCounterCache < Test::Unit::TestCase
263
+ def setup
264
+ teardown_db
265
+ setup_db
266
+ @root = TreeMixinWithCounterCache.create!
267
+ @child1 = TreeMixinWithCounterCache.create! :parent_id => @root.id
268
+ @child1_child1 = TreeMixinWithCounterCache.create! :parent_id => @child1.id
269
+ @child2 = TreeMixinWithCounterCache.create! :parent_id => @root.id
270
+ end
271
+
272
+ def teardown
273
+ teardown_db
274
+ end
275
+
276
+ def test_counter_cache
277
+ assert_equal 2, @root.reload.children_count
278
+ assert_equal 1, @child1.reload.children_count
279
+ end
280
+
281
+ def test_update_parents_counter_cache
282
+ @child1_child1.update_attributes(:parent_id => @root.id)
283
+ assert_equal 3, @root.reload.children_count
284
+ assert_equal 0, @child1.reload.children_count
285
+ end
286
+
287
+ end
metadata CHANGED
@@ -1,63 +1,109 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: acts_as_tree
3
- version: !ruby/object:Gem::Version
4
- version: 0.1.1
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ prerelease:
5
6
  platform: ruby
6
- authors:
7
+ authors:
7
8
  - Erik Dahlstrand
8
9
  - Rails Core
10
+ - Mark Turner
11
+ - Swanand Pagnis
9
12
  autorequire:
10
13
  bindir: bin
11
14
  cert_chain: []
12
-
13
- date: 2010-02-04 00:00:00 +01:00
14
- default_executable:
15
- dependencies: []
16
-
17
- description: Specify this acts_as extension if you want to model a tree structure by providing a parent association and a children association.
18
- email: erik.dahlstrand@gmail.com
15
+ date: 2012-04-09 00:00:00.000000000 Z
16
+ dependencies:
17
+ - !ruby/object:Gem::Dependency
18
+ name: bundler
19
+ requirement: &70099568607080 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ! '>='
23
+ - !ruby/object:Gem::Version
24
+ version: 1.0.0
25
+ type: :development
26
+ prerelease: false
27
+ version_requirements: *70099568607080
28
+ - !ruby/object:Gem::Dependency
29
+ name: activerecord
30
+ requirement: &70099568606560 !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ! '>='
34
+ - !ruby/object:Gem::Version
35
+ version: 1.15.4.7794
36
+ type: :development
37
+ prerelease: false
38
+ version_requirements: *70099568606560
39
+ - !ruby/object:Gem::Dependency
40
+ name: rdoc
41
+ requirement: &70099568606180 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ type: :development
48
+ prerelease: false
49
+ version_requirements: *70099568606180
50
+ - !ruby/object:Gem::Dependency
51
+ name: sqlite3
52
+ requirement: &70099568605720 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ! '>='
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ type: :development
59
+ prerelease: false
60
+ version_requirements: *70099568605720
61
+ description: Specify this acts_as extension if you want to model a tree structure
62
+ by providing a parent association and a children association.
63
+ email:
64
+ - erik.dahlstrand@gmail.com
65
+ - mark@amerine.net
66
+ - swanand.pagnis@gmail.com
19
67
  executables: []
20
-
21
68
  extensions: []
22
-
23
- extra_rdoc_files:
24
- - README.rdoc
25
- files:
26
- - .document
69
+ extra_rdoc_files: []
70
+ files:
27
71
  - .gitignore
28
- - README.rdoc
72
+ - .travis.yml
73
+ - Gemfile
74
+ - README.md
29
75
  - Rakefile
30
- - VERSION
31
76
  - acts_as_tree.gemspec
77
+ - init.rb
32
78
  - lib/acts_as_tree.rb
79
+ - lib/acts_as_tree/active_record/acts/tree.rb
80
+ - lib/acts_as_tree/version.rb
33
81
  - test/acts_as_tree_test.rb
34
- has_rdoc: true
35
- homepage: http://github.com/erdah/acts_as_tree
82
+ homepage: https://github.com/amerine/acts_as_tree
36
83
  licenses: []
37
-
38
84
  post_install_message:
39
- rdoc_options:
85
+ rdoc_options:
40
86
  - --charset=UTF-8
41
- require_paths:
87
+ require_paths:
42
88
  - lib
43
- required_ruby_version: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: "0"
48
- version:
49
- required_rubygems_version: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - ">="
52
- - !ruby/object:Gem::Version
53
- version: "0"
54
- version:
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ required_rubygems_version: !ruby/object:Gem::Requirement
96
+ none: false
97
+ requirements:
98
+ - - ! '>='
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
55
101
  requirements: []
56
-
57
- rubyforge_project:
58
- rubygems_version: 1.3.5
102
+ rubyforge_project: acts_as_tree
103
+ rubygems_version: 1.8.11
59
104
  signing_key:
60
105
  specification_version: 3
61
- summary: Gem version of acts_as_tree Rails plugin.
62
- test_files:
106
+ summary: Provides a simple tree behaviour to active_record mdoels.
107
+ test_files:
63
108
  - test/acts_as_tree_test.rb
109
+ has_rdoc:
data/.document DELETED
@@ -1,2 +0,0 @@
1
- README.rdoc
2
- lib/**/*.rb
data/README.rdoc DELETED
@@ -1,31 +0,0 @@
1
- = acts_as_tree
2
-
3
- Specify this +acts_as+ extension if you want to model a tree structure by providing a parent association and a children
4
- association. This requires that you have a foreign key column, which by default is called +parent_id+.
5
-
6
- == Install
7
-
8
- gem install acts_as_tree --source http://gemcutter.org
9
-
10
- == Example
11
-
12
- class Category < ActiveRecord::Base
13
- acts_as_tree :order => "name"
14
- end
15
-
16
- Example:
17
- root
18
- \_ child1
19
- \_ subchild1
20
- \_ subchild2
21
-
22
- root = Category.create("name" => "root")
23
- child1 = root.children.create("name" => "child1")
24
- subchild1 = child1.children.create("name" => "subchild1")
25
-
26
- root.parent # => nil
27
- child1.parent # => root
28
- root.children # => [child1]
29
- root.children.first.children.first # => subchild1
30
-
31
- Copyright (c) 2007 David Heinemeier Hansson, released under the MIT license
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.1.1