Commit 9ea545f1c8e386bc11af13d2de7333d52d487c98
1 parent
5d01bf73
Exists in
master
and in
28 other branches
ActionItem466: cutting down the search space
do not query for children of those that have no children git-svn-id: https://svn.colivre.coop.br/svn/noosfero/trunk@2060 3f533792-8f58-4932-b0fe-aaf55b0a4547
Showing
6 changed files
with
82 additions
and
15 deletions
Show diff stats
db/migrate/042_add_children_count_to_articles_and_categories.rb
0 → 100644
... | ... | @@ -0,0 +1,18 @@ |
1 | +class AddChildrenCountToArticlesAndCategories < ActiveRecord::Migration | |
2 | + def self.up | |
3 | + add_column :articles, :children_count, :integer, :default => 0 | |
4 | + execute 'update articles set children_count = (select count(*) from articles a2 where (a2.parent_id = articles.id) )' | |
5 | + | |
6 | + add_column :article_versions, :children_count, :integer, :default => 0 | |
7 | + | |
8 | + add_column :categories, :children_count, :integer, :default => 0 | |
9 | + execute 'update categories set children_count = (select count(*) from categories c2 where (c2.parent_id = categories.id) )' | |
10 | + end | |
11 | + | |
12 | + def self.down | |
13 | + remove_column :articles, :children_count | |
14 | + remove_column :article_versions, :children_count | |
15 | + | |
16 | + remove_column :categories, :children_count | |
17 | + end | |
18 | +end | ... | ... |
db/schema.rb
... | ... | @@ -9,7 +9,7 @@ |
9 | 9 | # |
10 | 10 | # It's strongly recommended to check this file into your version control system. |
11 | 11 | |
12 | -ActiveRecord::Schema.define(:version => 41) do | |
12 | +ActiveRecord::Schema.define(:version => 42) do | |
13 | 13 | |
14 | 14 | create_table "article_versions", :force => true do |t| |
15 | 15 | t.integer "article_id" |
... | ... | @@ -35,6 +35,7 @@ ActiveRecord::Schema.define(:version => 41) do |
35 | 35 | t.boolean "published", :default => true |
36 | 36 | t.date "start_date" |
37 | 37 | t.date "end_date" |
38 | + t.integer "children_count", :default => 0 | |
38 | 39 | end |
39 | 40 | |
40 | 41 | create_table "articles", :force => true do |t| |
... | ... | @@ -61,6 +62,7 @@ ActiveRecord::Schema.define(:version => 41) do |
61 | 62 | t.boolean "published", :default => true |
62 | 63 | t.date "start_date" |
63 | 64 | t.date "end_date" |
65 | + t.integer "children_count", :default => 0 | |
64 | 66 | end |
65 | 67 | |
66 | 68 | create_table "articles_categories", :id => false, :force => true do |t| |
... | ... | @@ -96,6 +98,7 @@ ActiveRecord::Schema.define(:version => 41) do |
96 | 98 | t.float "lat" |
97 | 99 | t.float "lng" |
98 | 100 | t.boolean "display_in_menu", :default => false |
101 | + t.integer "children_count", :default => 0 | |
99 | 102 | end |
100 | 103 | |
101 | 104 | create_table "categories_profiles", :id => false, :force => true do |t| | ... | ... |
lib/acts_as_filesystem.rb
... | ... | @@ -12,12 +12,13 @@ module ActsAsFileSystem |
12 | 12 | # non-alphanumericd characters changed into dashed) |
13 | 13 | # * path (+:text+)- stores the full path of the object (the full path of |
14 | 14 | # the parent, a "/" and the slug of the object) |
15 | + # * children_count - a cache of the number of children elements. | |
15 | 16 | def acts_as_filesystem |
16 | 17 | |
17 | 18 | include ActsAsFileSystem::InstanceMethods |
18 | 19 | |
19 | 20 | # a filesystem is a tree |
20 | - acts_as_tree :order => 'name' | |
21 | + acts_as_tree :order => 'name', :counter_cache => :children_count | |
21 | 22 | |
22 | 23 | # calculate the right path |
23 | 24 | before_create do |record| |
... | ... | @@ -163,7 +164,7 @@ module ActsAsFileSystem |
163 | 164 | |
164 | 165 | while !current_level.empty? |
165 | 166 | result += current_level |
166 | - ids = current_level.map(&:id) | |
167 | + ids = current_level.select {|item| item.children_count > 0}.map(&:id) | |
167 | 168 | current_level = self.class.find(:all, :conditions => { :parent_id => ids}) |
168 | 169 | end |
169 | 170 | block ||= (lambda { |x| x }) | ... | ... |
test/unit/acts_as_filesystem_test.rb
... | ... | @@ -26,11 +26,14 @@ class ActsAsFilesystemTest < Test::Unit::TestCase |
26 | 26 | |
27 | 27 | a1 = profile.articles.build(:name => 'a1'); a1.save! |
28 | 28 | |
29 | - a1_1 = profile.articles.build(:name => 'a1.1'); a1_1.parent = a1; a1_1.save! | |
30 | - a1_2 = profile.articles.build(:name => 'a1.2'); a1_2.parent = a1; a1_2.save! | |
29 | + a1_1 = a1.children.create!(:name => 'a1.1', :profile => profile) | |
31 | 30 | |
32 | - a1_1_1 = profile.articles.build(:name => 'a1.1.1'); a1_1_1.parent = a1_1; a1_1_1.save! | |
33 | - a1_1_2 = profile.articles.build(:name => 'a1.1.2'); a1_1_2.parent = a1_1; a1_1_2.save! | |
31 | + a1_2 = a1.children.create!(:name => 'a1.2', :profile => profile) | |
32 | + | |
33 | + a1_1_1 = a1_1.children.create!(:name => 'a1.1.1', :profile => profile) | |
34 | + a1_1_2 = a1_1.children.create!(:name => 'a1.1.2', :profile => profile) | |
35 | + | |
36 | + a1.reload | |
34 | 37 | |
35 | 38 | assert_equivalent [a1, a1_1, a1_2, a1_1_1, a1_1_2], a1.map_traversal |
36 | 39 | end |
... | ... | @@ -40,11 +43,14 @@ class ActsAsFilesystemTest < Test::Unit::TestCase |
40 | 43 | |
41 | 44 | a1 = profile.articles.build(:name => 'a1'); a1.save! |
42 | 45 | |
43 | - a1_1 = profile.articles.build(:name => 'a1.1'); a1_1.parent = a1; a1_1.save! | |
44 | - a1_2 = profile.articles.build(:name => 'a1.2'); a1_2.parent = a1; a1_2.save! | |
46 | + a1_1 = a1.children.create!(:name => 'a1.1', :profile => profile) | |
47 | + | |
48 | + a1_2 = a1.children.create!(:name => 'a1.2', :profile => profile) | |
45 | 49 | |
46 | - a1_1_1 = profile.articles.build(:name => 'a1.1.1'); a1_1_1.parent = a1_1; a1_1_1.save! | |
47 | - a1_1_2 = profile.articles.build(:name => 'a1.1.2'); a1_1_2.parent = a1_1; a1_1_2.save! | |
50 | + a1_1_1 = a1_1.children.create!(:name => 'a1.1.1', :profile => profile) | |
51 | + a1_1_2 = a1_1.children.create!(:name => 'a1.1.2', :profile => profile) | |
52 | + | |
53 | + a1.reload | |
48 | 54 | |
49 | 55 | assert_equivalent [a1_1, a1_2, a1_1_1, a1_1_2].map(&:id), a1.all_children.map(&:id) |
50 | 56 | end |
... | ... | @@ -54,11 +60,14 @@ class ActsAsFilesystemTest < Test::Unit::TestCase |
54 | 60 | |
55 | 61 | a1 = profile.articles.build(:name => 'a1'); a1.save! |
56 | 62 | |
57 | - a1_1 = profile.articles.build(:name => 'a1.1'); a1_1.parent = a1; a1_1.save! | |
58 | - a1_2 = profile.articles.build(:name => 'a1.2'); a1_2.parent = a1; a1_2.save! | |
63 | + a1_1 = a1.children.create!(:name => 'a1.1', :profile => profile) | |
64 | + | |
65 | + a1_2 = a1.children.create!(:name => 'a1.2', :profile => profile) | |
59 | 66 | |
60 | - a1_1_1 = profile.articles.build(:name => 'a1.1.1'); a1_1_1.parent = a1_1; a1_1_1.save! | |
61 | - a1_1_2 = profile.articles.build(:name => 'a1.1.2'); a1_1_2.parent = a1_1; a1_1_2.save! | |
67 | + a1_1_1 = a1_1.children.create!(:name => 'a1.1.1', :profile => profile) | |
68 | + a1_1_2 = a1_1.children.create!(:name => 'a1.1.2', :profile => profile) | |
69 | + | |
70 | + a1.reload | |
62 | 71 | |
63 | 72 | assert_equivalent ['a1', 'a1.1', 'a1.2', 'a1.1.1', 'a1.1.2'], a1.map_traversal { |item| item.name } |
64 | 73 | |
... | ... | @@ -76,4 +85,11 @@ class ActsAsFilesystemTest < Test::Unit::TestCase |
76 | 85 | assert_equal 'd', a.full_name_without_leading(3) |
77 | 86 | end |
78 | 87 | |
88 | + should 'cache children count' do | |
89 | + profile = create_user('testinguser').person | |
90 | + a1 = profile.articles.create!(:name => 'a1') | |
91 | + a11 = profile.articles.create!(:name => 'a11', :parent => a1) | |
92 | + a12 = profile.articles.create!(:name => 'a12', :parent => a1) | |
93 | + end | |
94 | + | |
79 | 95 | end | ... | ... |
test/unit/article_test.rb
... | ... | @@ -55,6 +55,7 @@ class ArticleTest < Test::Unit::TestCase |
55 | 55 | b.save! |
56 | 56 | assert_equal 'my-article/child-article', b.path |
57 | 57 | |
58 | + a = Article.find(a.id); | |
58 | 59 | a.name = 'another name' |
59 | 60 | a.save! |
60 | 61 | |
... | ... | @@ -308,4 +309,19 @@ class ArticleTest < Test::Unit::TestCase |
308 | 309 | assert_includes Article.find_by_contents('anything'), art |
309 | 310 | end |
310 | 311 | |
312 | + should 'cache children count' do | |
313 | + owner = create_user('testuser').person | |
314 | + art = owner.articles.build(:name => 'ytest'); art.save! | |
315 | + | |
316 | + # two children articles | |
317 | + art.children.create!(:profile => owner, :name => 'c1') | |
318 | + art.children.create!(:profile => owner, :name => 'c2') | |
319 | + | |
320 | + art.reload | |
321 | + | |
322 | + assert_equal 2, art.children_count | |
323 | + assert_equal 2, art.children.size | |
324 | + | |
325 | + end | |
326 | + | |
311 | 327 | end | ... | ... |
test/unit/category_test.rb
... | ... | @@ -418,4 +418,17 @@ class CategoryTest < Test::Unit::TestCase |
418 | 418 | assert_equivalent [c1, c11, c2], c.children_for_menu |
419 | 419 | end |
420 | 420 | |
421 | + should 'cache children count' do | |
422 | + c = Category.create!(:name => 'test', :environment => Environment.default) | |
423 | + | |
424 | + # two children catagories | |
425 | + c.children.create!(:name => 'test1', :environment => Environment.default) | |
426 | + c.children.create!(:name => 'test2', :environment => Environment.default) | |
427 | + | |
428 | + c.reload | |
429 | + | |
430 | + assert_equal 2, c.children_count | |
431 | + assert_equal 2, c.children.size | |
432 | + end | |
433 | + | |
421 | 434 | end | ... | ... |