acts_as_tree 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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