acts_as_happy_tree 1.0.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/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: []