acts_as_happy_tree 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,28 @@
1
+ acts_as_happy_tree
2
+ ============
3
+
4
+ Specify this +acts_as+ extension if you want to model a tree structure by providing a parent association and a children
5
+ association. This requires that you have a foreign key column, which by default is called +parent_id+.
6
+
7
+ class Category < ActiveRecord::Base
8
+ acts_as_happy_tree :order => "name"
9
+ end
10
+
11
+ Example:
12
+ root
13
+ \_ child1
14
+ \_ subchild1
15
+ \_ subchild2
16
+
17
+ root = Category.create("name" => "root")
18
+ child1 = root.children.create("name" => "child1")
19
+ subchild1 = child1.children.create("name" => "subchild1")
20
+
21
+ root.parent # => nil
22
+ child1.parent # => root
23
+ root.children # => [child1]
24
+ root.children.first.children.first # => subchild1
25
+
26
+ Copyright (c) 2007 David Heinemeier Hansson, released under the MIT license
27
+
28
+ Includes patch from http://dev.rubyonrails.org/ticket/1924
data/Rakefile ADDED
@@ -0,0 +1,73 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "acts_as_happy_tree"
8
+ gem.summary = %Q{acts_as_happy_tree as a gem}
9
+ gem.description = %Q{acts_as_happy_tree as a gem}
10
+ gem.email = "jim@saturnflyer.com"
11
+ gem.homepage = "http://github.com/saturnflyer/acts_as_happy_tree"
12
+ gem.authors = ["David Heinemeier Hansson",'and others']
13
+ # gem.add_development_dependency "thoughtbot-shoulda"
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ end
16
+ rescue LoadError
17
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
18
+ end
19
+
20
+ require 'rake/testtask'
21
+ Rake::TestTask.new(:test) do |test|
22
+ test.libs << 'lib' << 'test'
23
+ test.test_files = FileList['test/*_test.rb']
24
+ test.verbose = true
25
+ end
26
+
27
+ task 'test:ar30' do
28
+ ENV['AR_VERSION'] = '3.0.10'
29
+ Rake::Task["test"].execute
30
+ end
31
+
32
+ task 'test:ar31' do
33
+ ENV['AR_VERSION'] = '3.1.2'
34
+ Rake::Task["test"].execute
35
+ end
36
+
37
+ task 'test:ar32' do
38
+ ENV['AR_VERSION'] = '3.2.1'
39
+ Rake::Task["test"].execute
40
+ end
41
+
42
+ task 'test:all' => ['test:ar32', 'test:ar31', 'test:ar30']
43
+
44
+ begin
45
+ require 'rcov/rcovtask'
46
+ Rcov::RcovTask.new do |test|
47
+ test.libs << 'test'
48
+ test.pattern = 'test/**/*_test.rb'
49
+ test.verbose = true
50
+ end
51
+ rescue LoadError
52
+ task :rcov do
53
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
54
+ end
55
+ end
56
+
57
+ task :test => :check_dependencies
58
+
59
+ task :default => :test
60
+
61
+ require 'rake/rdoctask'
62
+ Rake::RDocTask.new do |rdoc|
63
+ if File.exist?('VERSION')
64
+ version = File.read('VERSION')
65
+ else
66
+ version = ""
67
+ end
68
+
69
+ rdoc.rdoc_dir = 'rdoc'
70
+ rdoc.title = "acts_as_happy_tree #{version}"
71
+ rdoc.rdoc_files.include('README*')
72
+ rdoc.rdoc_files.include('lib/**/*.rb')
73
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
@@ -0,0 +1,41 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{acts_as_happy_tree}
8
+ s.version = "1.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["David Heinemeier Hansson", "Jim Gay", "thoughtafter", "and others"]
12
+ s.date = %q{2012-08-18}
13
+ s.description = %q{Forked from acts_as_tree this should be a drop in replacement but with more features and tuned for performance and efficiency.}
14
+ s.email = %q{thoughtafter@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "README"
17
+ ]
18
+ s.files = [
19
+ "README",
20
+ "Rakefile",
21
+ "VERSION",
22
+ "acts_as_happy_tree.gemspec",
23
+ "init.rb",
24
+ "rails/init.rb",
25
+ "test/acts_as_happy_tree_test.rb"
26
+ ]
27
+ s.homepage = %q{http://github.com/thoughtafter/acts_as_happy_tree}
28
+ s.require_paths = ["lib"]
29
+ s.rubygems_version = %q{1.0.0}
30
+ s.summary = %q{acts_as_happy_tree gem}
31
+
32
+ if s.respond_to? :specification_version then
33
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
34
+ s.specification_version = 3
35
+
36
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
37
+ else
38
+ end
39
+ else
40
+ end
41
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require File.dirname(__FILE__) + "/rails/init"
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'acts_as_happy_tree'
@@ -0,0 +1,515 @@
1
+ require 'test/unit'
2
+
3
+ puts "Requested AR VER: #{ENV['AR_VERSION']}"
4
+ gem 'activerecord', ENV['AR_VERSION']
5
+
6
+ require 'rubygems'
7
+ require 'active_record'
8
+
9
+ puts "Activated AR VER: #{ActiveRecord::VERSION::STRING}"
10
+
11
+ $:.unshift File.dirname(__FILE__) + '/../lib'
12
+ require File.dirname(__FILE__) + '/../init'
13
+
14
+ class Test::Unit::TestCase
15
+ def assert_queries(num = 1)
16
+ $query_count = 0
17
+ yield
18
+ ensure
19
+ assert_equal num, $query_count, "#{$query_count} instead of #{num} queries were executed."
20
+ end
21
+
22
+ def assert_no_queries(&block)
23
+ assert_queries(0, &block)
24
+ end
25
+ end
26
+
27
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
28
+
29
+ # AR keeps printing annoying schema statements
30
+ $stdout = StringIO.new
31
+
32
+ def setup_db
33
+ ActiveRecord::Base.logger
34
+ ActiveRecord::Schema.define(:version => 1) do
35
+ create_table :mixins do |t|
36
+ t.column :type, :string
37
+ t.column :parent_id, :integer
38
+ t.column :children_count, :integer, :default => 0
39
+ end
40
+ end
41
+ end
42
+
43
+ def teardown_db
44
+ ActiveRecord::Base.connection.tables.each do |table|
45
+ ActiveRecord::Base.connection.drop_table(table)
46
+ end
47
+ end
48
+
49
+ class Mixin < ActiveRecord::Base
50
+ end
51
+
52
+ class TreeMixin < Mixin
53
+ acts_as_happy_tree :foreign_key => "parent_id", :order => "id"
54
+ end
55
+
56
+ class TreeMixinWithCounterCache < Mixin
57
+ acts_as_happy_tree :foreign_key => "parent_id", :order => "id", :counter_cache => :children_count
58
+ end
59
+
60
+ class TreeMixinWithoutOrder < Mixin
61
+ acts_as_happy_tree :foreign_key => "parent_id"
62
+ end
63
+
64
+ class RecursivelyCascadedTreeMixin < Mixin
65
+ acts_as_happy_tree :foreign_key => "parent_id"
66
+ has_one :first_child, :class_name => 'RecursivelyCascadedTreeMixin', :foreign_key => :parent_id
67
+ end
68
+
69
+ class TreeMixinNullify < Mixin
70
+ acts_as_happy_tree :foreign_key => "parent_id", :order => "id", :dependent => :nullify
71
+ end
72
+
73
+ class TreeTest < Test::Unit::TestCase
74
+
75
+ def setup
76
+ setup_db
77
+ @root1 = TreeMixin.create!
78
+ @root_child1 = TreeMixin.create! :parent_id => @root1.id
79
+ @child1_child = TreeMixin.create! :parent_id => @root_child1.id
80
+ @root_child2 = TreeMixin.create! :parent_id => @root1.id
81
+ @root2 = TreeMixin.create!
82
+ @root3 = TreeMixin.create!
83
+ @root_child1.reload # need to reload to recognize children
84
+ end
85
+
86
+ def teardown
87
+ teardown_db
88
+ end
89
+
90
+ def test_children
91
+ assert_equal @root1.reload.children, [@root_child1, @root_child2]
92
+ assert_equal @root_child1.reload.children, [@child1_child]
93
+ assert_equal @child1_child.reload.children, []
94
+ assert_equal @root_child2.reload.children, []
95
+ end
96
+
97
+ def test_parent
98
+ assert_equal @root_child1.parent, @root1
99
+ assert_equal @root_child1.parent, @root_child2.parent
100
+ assert_nil @root1.parent
101
+ end
102
+
103
+ def test_nullify
104
+ root4 = TreeMixinNullify.create!
105
+ root4_child = TreeMixinNullify.create! :parent_id => root4.id
106
+ assert_equal 2, TreeMixinNullify.count
107
+ assert_equal root4.id, root4_child.parent_id
108
+ root4.destroy
109
+ assert_equal 1, TreeMixinNullify.count
110
+ assert_nil root4_child.reload.parent_id
111
+ end
112
+
113
+ def test_delete
114
+ assert_equal 6, TreeMixin.count
115
+ @root1.destroy
116
+ assert_equal 2, TreeMixin.count
117
+ @root2.destroy
118
+ @root3.destroy
119
+ assert_equal 0, TreeMixin.count
120
+ end
121
+
122
+ def test_insert
123
+ @extra = @root1.children.create
124
+
125
+ assert @extra
126
+
127
+ assert_equal @extra.parent, @root1
128
+
129
+ assert_equal 3, @root1.reload.children.count
130
+ assert @root1.children.include?(@extra)
131
+ assert @root1.children.include?(@root_child1)
132
+ assert @root1.children.include?(@root_child2)
133
+ end
134
+
135
+ def test_ancestors
136
+ assert_equal [], @root1.ancestors
137
+ assert_equal [@root1], @root_child1.ancestors
138
+ assert_equal [@root_child1, @root1], @child1_child.ancestors
139
+ assert_equal [@root1], @root_child2.ancestors
140
+ assert_equal [], @root2.ancestors
141
+ assert_equal [], @root3.ancestors
142
+ end
143
+
144
+ def test_ancestor_ids
145
+ assert_equal [], @root1.ancestor_ids
146
+ assert_equal [@root1.id], @root_child1.ancestor_ids
147
+ assert_equal [@root_child1.id, @root1.id], @child1_child.ancestor_ids
148
+ assert_equal [@root1.id], @root_child2.ancestor_ids
149
+ assert_equal [], @root2.ancestor_ids
150
+ assert_equal [], @root3.ancestor_ids
151
+ end
152
+
153
+ def test_ancestors_count
154
+ assert_equal 0, @root1.ancestors_count
155
+ assert_equal 1, @root_child1.ancestors_count
156
+ assert_equal 2, @child1_child.ancestors_count
157
+ assert_equal 1, @root_child2.ancestors_count
158
+ assert_equal 0, @root2.ancestors_count
159
+ assert_equal 0, @root3.ancestors_count
160
+ end
161
+
162
+ def test_class_root
163
+ assert_equal @root1, TreeMixin.root
164
+ end
165
+
166
+ def test_root
167
+ assert_equal @root1, @root1.root
168
+ assert_equal @root1, @root_child1.root
169
+ assert_equal @root1, @child1_child.root
170
+ assert_equal @root1, @root_child2.root
171
+ assert_equal @root2, @root2.root
172
+ assert_equal @root3, @root3.root
173
+ end
174
+
175
+ def test_root_id
176
+ assert_equal @root1.id, @root1.root_id
177
+ assert_equal @root1.id, @root_child1.root_id
178
+ assert_equal @root1.id, @child1_child.root_id
179
+ assert_equal @root1.id, @root_child2.root_id
180
+ assert_equal @root2.id, @root2.root_id
181
+ assert_equal @root3.id, @root3.root_id
182
+ end
183
+
184
+ def test_roots
185
+ assert_equal [@root1, @root2, @root3], TreeMixin.roots
186
+ end
187
+
188
+ def test_siblings
189
+ assert_equal [@root2, @root3], @root1.siblings
190
+ assert_equal [@root_child2], @root_child1.siblings
191
+ assert_equal [], @child1_child.siblings
192
+ assert_equal [@root_child1], @root_child2.siblings
193
+ assert_equal [@root1, @root3], @root2.siblings
194
+ assert_equal [@root1, @root2], @root3.siblings
195
+ end
196
+
197
+ def test_self_and_siblings
198
+ assert_equal [@root1, @root2, @root3], @root1.self_and_siblings
199
+ assert_equal [@root_child1, @root_child2], @root_child1.self_and_siblings
200
+ assert_equal [@child1_child], @child1_child.self_and_siblings
201
+ assert_equal [@root_child1, @root_child2], @root_child2.self_and_siblings
202
+ assert_equal [@root1, @root2, @root3], @root2.self_and_siblings
203
+ assert_equal [@root1, @root2, @root3], @root3.self_and_siblings
204
+ end
205
+
206
+ def test_root?
207
+ assert @root1.root?
208
+ assert @root2.root?
209
+ assert @root3.root?
210
+ assert !@root_child1.root?
211
+ assert !@root_child2.root?
212
+ assert !@child1_child.root?
213
+ end
214
+
215
+ def test_child?
216
+ assert !@root1.child?
217
+ assert !@root2.child?
218
+ assert !@root3.child?
219
+ assert @root_child1.child?
220
+ assert @root_child2.child?
221
+ assert @child1_child.child?
222
+ end
223
+
224
+ def test_parent?
225
+ assert @root1.parent?
226
+ assert !@root2.parent?
227
+ assert !@root3.parent?
228
+ assert @root_child1.parent?
229
+ assert !@root_child2.parent?
230
+ assert !@child1_child.parent?
231
+ end
232
+
233
+ def test_leaf?
234
+ assert !@root1.leaf?
235
+ assert @root2.leaf?
236
+ assert @root3.leaf?
237
+ assert !@root_child1.leaf?
238
+ assert @root_child2.leaf?
239
+ assert @child1_child.leaf?
240
+ end
241
+
242
+ def test_ancestor_of?
243
+ assert_equal false, @root1.ancestor_of?(nil)
244
+ assert_equal false, @root_child1.ancestor_of?(nil)
245
+ assert_equal false, @root_child2.ancestor_of?(nil)
246
+ assert_equal false, @child1_child.ancestor_of?(nil)
247
+
248
+ assert_equal false, @root1.ancestor_of?(0)
249
+ assert_equal false, @root_child1.ancestor_of?("foo")
250
+ assert_equal false, @root_child2.ancestor_of?(:bar)
251
+ assert_equal false, @child1_child.ancestor_of?(TreeMixin.new)
252
+
253
+ assert_equal true, @root1.ancestor_of?(@root_child1)
254
+ assert_equal true, @root1.ancestor_of?(@root_child2)
255
+ assert_equal true, @root1.ancestor_of?(@child1_child)
256
+
257
+ assert_equal false, @root_child1.ancestor_of?(@root1)
258
+ assert_equal false, @root_child2.ancestor_of?(@root1)
259
+ assert_equal false, @child1_child.ancestor_of?(@root1)
260
+
261
+ assert_equal false, @root1.ancestor_of?(@root1)
262
+ assert_equal false, @root1.ancestor_of?(@root2)
263
+ assert_equal false, @root1.ancestor_of?(@root3)
264
+
265
+ assert_equal true, @root_child1.ancestor_of?(@child1_child)
266
+ assert_equal false, @child1_child.ancestor_of?(@root_child1)
267
+ end
268
+
269
+ def test_descendant_of?
270
+ assert_equal false, @root1.descendant_of?(nil)
271
+ assert_equal false, @root_child1.descendant_of?(nil)
272
+ assert_equal false, @root_child2.descendant_of?(nil)
273
+ assert_equal false, @child1_child.descendant_of?(nil)
274
+
275
+ assert_equal false, @root1.descendant_of?(0)
276
+ assert_equal false, @root_child1.descendant_of?("foo")
277
+ assert_equal false, @root_child2.descendant_of?(:bar)
278
+ assert_equal false, @child1_child.descendant_of?(TreeMixin.new)
279
+
280
+ assert_equal false, @root1.descendant_of?(@root_child1)
281
+ assert_equal false, @root1.descendant_of?(@root_child2)
282
+ assert_equal false, @root1.descendant_of?(@child1_child)
283
+
284
+ assert_equal true, @root_child1.descendant_of?(@root1)
285
+ assert_equal true, @root_child2.descendant_of?(@root1)
286
+ assert_equal true, @child1_child.descendant_of?(@root1)
287
+
288
+ assert_equal false, @root1.descendant_of?(@root1)
289
+ assert_equal false, @root1.descendant_of?(@root2)
290
+ assert_equal false, @root1.descendant_of?(@root3)
291
+
292
+ assert_equal false, @root_child1.descendant_of?(@child1_child)
293
+ assert_equal true, @child1_child.descendant_of?(@root_child1)
294
+ end
295
+
296
+ def test_child_ids
297
+ assert_equal [@root_child1.id, @root_child2.id], @root1.child_ids
298
+ assert_equal [@child1_child.id], @root_child1.child_ids
299
+ end
300
+
301
+ def do_test_descendants_dfs(method, *args)
302
+ assert_equal [@root_child1, @child1_child, @root_child2], @root1.send(method, *args)
303
+ assert_equal [@child1_child], @root_child1.send(method, *args)
304
+ end
305
+
306
+ def test_descendants
307
+ do_test_descendants_dfs('descendants')
308
+ end
309
+
310
+ def test_descendants_classic
311
+ do_test_descendants_dfs('descendants_classic')
312
+ do_test_descendants_dfs('descendants', :traversal=>:classic)
313
+ end
314
+
315
+ def test_descendants_dfs
316
+ do_test_descendants_dfs('descendants_dfs')
317
+ do_test_descendants_dfs('descendants', :traversal=>:dfs)
318
+ end
319
+
320
+ def test_descendants_dfs_rec
321
+ do_test_descendants_dfs('descendants_dfs_rec')
322
+ do_test_descendants_dfs('descendants', :traversal=>:dfs_rec)
323
+ end
324
+
325
+ def do_test_descendants_bfs(method, *params)
326
+ assert_equal [@root_child1, @root_child2, @child1_child], @root1.send(method, *params)
327
+ assert_equal [@child1_child], @root_child1.send(method, *params)
328
+ end
329
+
330
+ def test_descendants_bfs
331
+ do_test_descendants_bfs('descendants_bfs')
332
+ do_test_descendants_bfs('descendants', :traversal=>:bfs)
333
+ end
334
+
335
+ def test_descendants_bfs_rec
336
+ do_test_descendants_bfs('descendants_bfs_rec')
337
+ do_test_descendants_bfs('descendants', :traversal=>:bfs_rec)
338
+ end
339
+
340
+ def do_test_self_and_descendants_dfs(method)
341
+ assert_equal [@root1, @root_child1, @child1_child, @root_child2], @root1.send(method)
342
+ assert_equal [@root_child1, @child1_child], @root_child1.send(method)
343
+ end
344
+
345
+ def test_self_and_descendants
346
+ do_test_self_and_descendants_dfs('self_and_descendants')
347
+ end
348
+
349
+ def test_self_and_descendants_dfs
350
+ do_test_self_and_descendants_dfs('self_and_descendants_dfs')
351
+ end
352
+
353
+ def test_self_and_descendants_bfs
354
+ assert_equal [@root1, @root_child1, @root_child2, @child1_child], @root1.self_and_descendants_bfs
355
+ assert_equal [@root_child1, @child1_child], @root_child1.self_and_descendants_bfs
356
+ end
357
+
358
+ def do_test_descendant_ids_dfs(method)
359
+ assert_equal [@root_child1, @child1_child, @root_child2].map(&:id),
360
+ @root1.send(method)
361
+ assert_equal [@child1_child].map(&:id), @root_child1.send(method)
362
+ end
363
+
364
+ def test_descendant_ids
365
+ do_test_descendant_ids_dfs('descendant_ids')
366
+ end
367
+
368
+ def test_descendant_ids_dfs
369
+ do_test_descendant_ids_dfs('descendant_ids_dfs')
370
+ end
371
+
372
+ def test_descendant_ids_dfs_rec
373
+ do_test_descendant_ids_dfs('descendant_ids_dfs_rec')
374
+ end
375
+
376
+ def do_test_descendant_ids_bfs(method)
377
+ assert_equal [@root_child1, @root_child2, @child1_child].map(&:id),
378
+ @root1.send(method)
379
+ assert_equal [@child1_child].map(&:id), @root_child1.send(method)
380
+ end
381
+
382
+ def test_descendant_ids_bfs
383
+ do_test_descendant_ids_bfs('descendant_ids_bfs')
384
+ end
385
+
386
+ def test_descendant_ids_bfs_rec
387
+ do_test_descendant_ids_bfs('descendant_ids_bfs_rec')
388
+ end
389
+
390
+ def do_test_descendants_count(counter)
391
+ assert_equal 3, @root1.send(counter)
392
+ assert_equal 0, @root2.send(counter)
393
+ assert_equal 0, @root3.send(counter)
394
+ assert_equal 1, @root_child1.send(counter)
395
+ assert_equal 0, @root_child2.send(counter)
396
+ assert_equal 0, @child1_child.send(counter)
397
+ end
398
+
399
+ def test_descendants_count
400
+ do_test_descendants_count(:descendants_count)
401
+ end
402
+
403
+ def test_descendants_count_dfs
404
+ do_test_descendants_count(:descendants_count_dfs)
405
+ end
406
+
407
+ def test_descendants_count_bfs
408
+ do_test_descendants_count(:descendants_count_bfs)
409
+ end
410
+
411
+ def test_descendants_count_dfs_rec
412
+ do_test_descendants_count(:descendants_count_dfs_rec)
413
+ end
414
+
415
+ def test_descendants_count_bfs_rec
416
+ do_test_descendants_count(:descendants_count_bfs_rec)
417
+ end
418
+ end
419
+
420
+ class TreeTestWithCounterCache < Test::Unit::TestCase
421
+ def setup
422
+ teardown_db
423
+ setup_db
424
+ @root = TreeMixinWithCounterCache.create!
425
+ @child1 = TreeMixinWithCounterCache.create! :parent_id => @root.id
426
+ @child1_child1 = TreeMixinWithCounterCache.create! :parent_id => @child1.id
427
+ @child2 = TreeMixinWithCounterCache.create! :parent_id => @root.id
428
+ end
429
+
430
+ def teardown
431
+ teardown_db
432
+ end
433
+
434
+ def test_counter_cache
435
+ assert_equal 2, @root.reload.children_count
436
+ assert_equal 1, @child1.reload.children_count
437
+ end
438
+
439
+ def test_update_parents_counter_cache
440
+ @child1_child1.update_attributes(:parent_id => @root.id)
441
+ assert_equal 3, @root.reload.children_count
442
+ assert_equal 0, @child1.reload.children_count
443
+ end
444
+
445
+ end
446
+
447
+
448
+ class TreeTestWithEagerLoading < Test::Unit::TestCase
449
+
450
+ def setup
451
+ teardown_db
452
+ setup_db
453
+ @root1 = TreeMixin.create!
454
+ @root_child1 = TreeMixin.create! :parent_id => @root1.id
455
+ @child1_child = TreeMixin.create! :parent_id => @root_child1.id
456
+ @root_child2 = TreeMixin.create! :parent_id => @root1.id
457
+ @root2 = TreeMixin.create!
458
+ @root3 = TreeMixin.create!
459
+
460
+ @rc1 = RecursivelyCascadedTreeMixin.create!
461
+ @rc2 = RecursivelyCascadedTreeMixin.create! :parent_id => @rc1.id
462
+ @rc3 = RecursivelyCascadedTreeMixin.create! :parent_id => @rc2.id
463
+ @rc4 = RecursivelyCascadedTreeMixin.create! :parent_id => @rc3.id
464
+ end
465
+
466
+ def teardown
467
+ teardown_db
468
+ end
469
+
470
+ def test_eager_association_loading
471
+ roots = TreeMixin.find(:all, :include => :children, :conditions => "mixins.parent_id IS NULL", :order => "mixins.id")
472
+ assert_equal [@root1, @root2, @root3], roots
473
+ assert_no_queries do
474
+ assert_equal 2, roots[0].children.count
475
+ assert_equal 0, roots[1].children.count
476
+ assert_equal 0, roots[2].children.count
477
+ end
478
+ end
479
+
480
+ def test_eager_association_loading_with_recursive_cascading_three_levels_has_many
481
+ root_node = RecursivelyCascadedTreeMixin.find(:first, :include => { :children => { :children => :children } }, :order => 'mixins.id')
482
+ assert_equal @rc4, assert_no_queries { root_node.children.first.children.first.children.first }
483
+ end
484
+
485
+ def test_eager_association_loading_with_recursive_cascading_three_levels_has_one
486
+ root_node = RecursivelyCascadedTreeMixin.find(:first, :include => { :first_child => { :first_child => :first_child } }, :order => 'mixins.id')
487
+ assert_equal @rc4, assert_no_queries { root_node.first_child.first_child.first_child }
488
+ end
489
+
490
+ def test_eager_association_loading_with_recursive_cascading_three_levels_belongs_to
491
+ leaf_node = RecursivelyCascadedTreeMixin.find(:first, :include => { :parent => { :parent => :parent } }, :order => 'mixins.id DESC')
492
+ assert_equal @rc1, assert_no_queries { leaf_node.parent.parent.parent }
493
+ end
494
+ end
495
+
496
+ class TreeTestWithoutOrder < Test::Unit::TestCase
497
+
498
+ def setup
499
+ setup_db
500
+ @root1 = TreeMixinWithoutOrder.create!
501
+ @root2 = TreeMixinWithoutOrder.create!
502
+ end
503
+
504
+ def teardown
505
+ teardown_db
506
+ end
507
+
508
+ def test_root
509
+ assert [@root1, @root2].include?(TreeMixinWithoutOrder.root)
510
+ end
511
+
512
+ def test_roots
513
+ assert_equal [], [@root1, @root2] - TreeMixinWithoutOrder.roots
514
+ end
515
+ end
metadata ADDED
@@ -0,0 +1,56 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: acts_as_happy_tree
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - David Heinemeier Hansson
9
+ - Jim Gay
10
+ - thoughtafter
11
+ - and others
12
+ autorequire:
13
+ bindir: bin
14
+ cert_chain: []
15
+ date: 2012-08-18 00:00:00.000000000 Z
16
+ dependencies: []
17
+ description: Forked from acts_as_tree this should be a drop in replacement but with
18
+ more features and tuned for performance and efficiency.
19
+ email: thoughtafter@gmail.com
20
+ executables: []
21
+ extensions: []
22
+ extra_rdoc_files:
23
+ - README
24
+ files:
25
+ - README
26
+ - Rakefile
27
+ - VERSION
28
+ - acts_as_happy_tree.gemspec
29
+ - init.rb
30
+ - rails/init.rb
31
+ - test/acts_as_happy_tree_test.rb
32
+ homepage: http://github.com/thoughtafter/acts_as_happy_tree
33
+ licenses: []
34
+ post_install_message:
35
+ rdoc_options: []
36
+ require_paths:
37
+ - lib
38
+ required_ruby_version: !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ required_rubygems_version: !ruby/object:Gem::Requirement
45
+ none: false
46
+ requirements:
47
+ - - ! '>='
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ requirements: []
51
+ rubyforge_project:
52
+ rubygems_version: 1.8.11
53
+ signing_key:
54
+ specification_version: 3
55
+ summary: acts_as_happy_tree gem
56
+ test_files: []