Commit cc17d60a3936837afdc7a2dfcefe51acbe27eb5f
1 parent
cdde5e0b
Exists in
master
and in
29 other branches
ActionItem253: fixed a bug where article categorized in more than one categories…
… in a given subtree is returned twice when searchin for the top category git-svn-id: https://svn.colivre.coop.br/svn/noosfero/trunk@1716 3f533792-8f58-4932-b0fe-aaf55b0a4547
Showing
4 changed files
with
96 additions
and
29 deletions
Show diff stats
app/controllers/public/search_controller.rb
... | ... | @@ -38,7 +38,7 @@ class SearchController < ApplicationController |
38 | 38 | def action_category |
39 | 39 | @recent_articles = @finder.recent('articles') |
40 | 40 | @recent_comments = @finder.recent('comments') |
41 | - @most_commented_articles = category.most_commented_articles | |
41 | + @most_commented_articles = @finder.most_commented_articles | |
42 | 42 | end |
43 | 43 | alias :action_region :action_category |
44 | 44 | |
... | ... | @@ -76,7 +76,7 @@ class SearchController < ApplicationController |
76 | 76 | |
77 | 77 | # view the summary of one category |
78 | 78 | def category_index |
79 | - send('action_' + @category.class.name.underscore) | |
79 | + send('action_' + category.class.name.underscore) | |
80 | 80 | end |
81 | 81 | attr_reader :category |
82 | 82 | ... | ... |
app/models/category_finder.rb
... | ... | @@ -24,33 +24,49 @@ class CategoryFinder |
24 | 24 | end |
25 | 25 | |
26 | 26 | def products(query='*', options={}) |
27 | - Product.find_by_contents(query, {}, {:select => 'products.*', :joins => 'inner join categories_profiles on products.enterprise_id = categories_profiles.profile_id', :conditions => ['categories_profiles.category_id in (?)', category_ids]}.merge!(options)) | |
27 | + find_in_categorized(Product, query, options) | |
28 | 28 | end |
29 | 29 | |
30 | 30 | def comments(query='*', options={}) |
31 | - Comment.find_by_contents(query, {}, {:select => 'comments.*', :joins => 'inner join articles_categories on articles_categories.article_id = comments.article_id', :conditions => ['articles_categories.category_id in (?)', category_ids]}.merge!(options)) | |
31 | + find_in_categorized(Comment, query, options) | |
32 | 32 | end |
33 | 33 | |
34 | 34 | def recent(asset, limit = 10) |
35 | - table = case asset | |
36 | - when 'people', 'communities', 'enterprises' | |
37 | - 'profiles' | |
38 | - else | |
39 | - asset | |
40 | - end | |
41 | - | |
42 | - with_options :limit => limit, :order => "created_at desc, #{table}.id desc" do |finder| | |
43 | - finder.send(asset, '*', {}) | |
44 | - end | |
35 | + asset_class(asset).find(:all, options_for_find(asset_class(asset), {:limit => limit, :order => "created_at desc, #{asset_table(asset)}.id desc"})) | |
45 | 36 | end |
46 | 37 | |
47 | 38 | def count(asset) |
48 | - send(asset).size | |
39 | + asset_class(asset).count(:all, options_for_find(asset_class(asset))) | |
40 | + end | |
41 | + | |
42 | + def most_commented_articles(limit=10) | |
43 | + Article.find(:all, options_for_find(Article, :limit => limit, :order => 'comments_count DESC')) | |
49 | 44 | end |
50 | 45 | |
51 | 46 | protected |
52 | 47 | |
53 | 48 | def find_in_categorized(klass, query, options={}) |
54 | - klass.find_by_contents(query, {}, {:include => 'categories', :conditions => ['categories.id IN (?)', category_ids]}.merge!(options)) | |
49 | + klass.find_by_contents(query, {}, options_for_find(klass, options)).uniq | |
50 | + end | |
51 | + | |
52 | + def options_for_find(klass, options={}) | |
53 | + case klass.name | |
54 | + when 'Comment' | |
55 | + {:select => 'distinct comments.*', :joins => 'inner join articles_categories on articles_categories.article_id = comments.article_id', :conditions => ['articles_categories.category_id in (?)', category_ids]}.merge!(options) | |
56 | + when 'Product' | |
57 | + {:select => 'distinct products.*', :joins => 'inner join categories_profiles on products.enterprise_id = categories_profiles.profile_id', :conditions => ['categories_profiles.category_id in (?)', category_ids]}.merge!(options) | |
58 | + when 'Article', 'Person', 'Community', 'Enterprise' | |
59 | + {:include => 'categories', :conditions => ['categories.id IN (?)', category_ids]}.merge!(options) | |
60 | + else | |
61 | + raise "unreconized class #{klass.name}" | |
62 | + end | |
63 | + end | |
64 | + | |
65 | + def asset_class(asset) | |
66 | + asset.to_s.singularize.camelize.constantize | |
67 | + end | |
68 | + | |
69 | + def asset_table(asset) | |
70 | + asset_class(asset).table_name | |
55 | 71 | end |
56 | 72 | end | ... | ... |
test/functional/search_controller_test.rb
... | ... | @@ -31,9 +31,9 @@ class SearchControllerTest < Test::Unit::TestCase |
31 | 31 | |
32 | 32 | should 'search with filtered query' do |
33 | 33 | @controller.expects(:locale).returns('pt_BR').at_least_once |
34 | - @controller.expects(:search).with(anything, 'carne vaca').at_least_once | |
35 | - @controller.expects(:search).with(anything, 'a carne da vaca').never | |
36 | 34 | get 'index', :query => 'a carne da vaca' |
35 | + | |
36 | + assert_equal 'carne vaca', assigns('filtered_query') | |
37 | 37 | end |
38 | 38 | |
39 | 39 | should 'search only in specified types of content' do |
... | ... | @@ -250,7 +250,7 @@ class SearchControllerTest < Test::Unit::TestCase |
250 | 250 | p2 = create_user('test2').person |
251 | 251 | |
252 | 252 | get :assets, :asset => 'people', :category_path => [ 'my-category' ] |
253 | - assert_equal [p1], assigns(:results)[:people].instance_variable_get('@results') | |
253 | + assert_equal [p1], assigns(:results)[:people] | |
254 | 254 | end |
255 | 255 | |
256 | 256 | should 'find communities' do |
... | ... | @@ -293,7 +293,7 @@ class SearchControllerTest < Test::Unit::TestCase |
293 | 293 | |
294 | 294 | get :assets, :asset => 'communities', :category_path => [ 'my-category' ] |
295 | 295 | |
296 | - assert_equal [c3, c1], assigns(:results)[:communities].instance_variable_get('@results') | |
296 | + assert_equal [c3, c1], assigns(:results)[:communities] | |
297 | 297 | end |
298 | 298 | |
299 | 299 | should 'find products' do |
... | ... | @@ -379,7 +379,7 @@ class SearchControllerTest < Test::Unit::TestCase |
379 | 379 | } |
380 | 380 | names.each do |thing,description| |
381 | 381 | assert_tag :tag => 'input', :attributes => { :type => 'checkbox', :name => "find_in[]", :value => thing.to_s, :checked => 'checked' } |
382 | - assert_tag :tag => 'span', :content => description | |
382 | + assert_tag :tag => 'label', :content => description | |
383 | 383 | end |
384 | 384 | end |
385 | 385 | |
... | ... | @@ -435,7 +435,10 @@ class SearchControllerTest < Test::Unit::TestCase |
435 | 435 | should 'list recent articles in the category' do |
436 | 436 | @controller.expects(:category).returns(@category).at_least_once |
437 | 437 | recent = [] |
438 | - @category.expects(:recent_articles).returns(recent) | |
438 | + finder = CategoryFinder.new(@category) | |
439 | + finder.expects(:recent).with('comments').returns(recent) | |
440 | + finder.expects(:recent).with('articles').returns(recent) | |
441 | + CategoryFinder.expects(:new).with(@category).returns(finder) | |
439 | 442 | |
440 | 443 | get :category_index, :category_path => [ 'my-category' ] |
441 | 444 | assert_same recent, assigns(:recent_articles) |
... | ... | @@ -444,7 +447,10 @@ class SearchControllerTest < Test::Unit::TestCase |
444 | 447 | should 'list recent comments in the category' do |
445 | 448 | @controller.expects(:category).returns(@category).at_least_once |
446 | 449 | recent = [] |
447 | - @category.expects(:recent_comments).returns(recent) | |
450 | + finder = CategoryFinder.new(@category) | |
451 | + finder.expects(:recent).with('comments').returns(recent) | |
452 | + finder.expects(:recent).with('articles').returns(recent) | |
453 | + CategoryFinder.expects(:new).with(@category).returns(finder) | |
448 | 454 | |
449 | 455 | get :category_index, :category_path => [ 'my-category' ] |
450 | 456 | assert_same recent, assigns(:recent_comments) |
... | ... | @@ -453,7 +459,9 @@ class SearchControllerTest < Test::Unit::TestCase |
453 | 459 | should 'list most commented articles in the category' do |
454 | 460 | @controller.expects(:category).returns(@category).at_least_once |
455 | 461 | most_commented = [] |
456 | - @category.expects(:most_commented_articles).returns(most_commented) | |
462 | + finder = CategoryFinder.new(@category) | |
463 | + finder.expects(:most_commented_articles).returns(most_commented) | |
464 | + CategoryFinder.expects(:new).with(@category).returns(finder) | |
457 | 465 | |
458 | 466 | get :category_index, :category_path => [ 'my-category' ] |
459 | 467 | assert_same most_commented, assigns(:most_commented_articles) |
... | ... | @@ -509,7 +517,7 @@ class SearchControllerTest < Test::Unit::TestCase |
509 | 517 | child = Category.create!(:name => "Child Category", :environment => Environment.default, :parent => parent) |
510 | 518 | |
511 | 519 | get :index, :category_path => [ 'parent-category', 'child-category' ], :query => 'a sample search' |
512 | - assert_tag :tag => 'h2', :content => /Search results for "a sample search" in "Child Category"/ | |
520 | + assert_tag :tag => 'h1', :content => /Search results for "a sample search" in "Child Category"/ | |
513 | 521 | end |
514 | 522 | |
515 | 523 | should 'search in categoty hierachy' do | ... | ... |
test/unit/category_finder_test.rb
... | ... | @@ -88,9 +88,9 @@ class CategoryFinderTest < ActiveSupport::TestCase |
88 | 88 | end |
89 | 89 | |
90 | 90 | should 'search in category hierarchy' do |
91 | - parent = Category.create!(:name => 'child category', :environment => Environment.default) | |
91 | + parent = Category.create!(:name => 'parent category', :environment => Environment.default) | |
92 | 92 | child = Category.create!(:name => 'child category', :environment => Environment.default, :parent => parent) |
93 | - p1 = create_user('people_1').person; p1.name = 'a beautiful person'; p1.categories << parent; p1.save! | |
93 | + p1 = create_user('people_1').person; p1.name = 'a beautiful person'; p1.categories << child; p1.save! | |
94 | 94 | |
95 | 95 | f = CategoryFinder.new(parent) |
96 | 96 | assert_includes f.people, p1 |
... | ... | @@ -105,8 +105,8 @@ class CategoryFinderTest < ActiveSupport::TestCase |
105 | 105 | ent1 = Enterprise.create!(:name => 'teste1', :identifier => 'teste1', :categories => [@category]) |
106 | 106 | ent2 = Enterprise.create!(:name => 'teste2', :identifier => 'teste2', :categories => [@category]) |
107 | 107 | recent = @finder.recent('enterprises', 1) |
108 | - assert_includes recent, ent1 | |
109 | - assert_not_includes recent, ent2 | |
108 | + assert_includes recent, ent2 | |
109 | + assert_not_includes recent, ent1 | |
110 | 110 | end |
111 | 111 | |
112 | 112 | should 'count entrprises' do |
... | ... | @@ -114,4 +114,47 @@ class CategoryFinderTest < ActiveSupport::TestCase |
114 | 114 | ent1 = Enterprise.create!(:name => 'teste1', :identifier => 'teste1', :categories => [@category]) |
115 | 115 | assert_equal count+1, @finder.count('enterprises') |
116 | 116 | end |
117 | + | |
118 | + should 'not list more people than limit' do | |
119 | + p1 = create_user('test1').person; p1.categories << @category | |
120 | + p2 = create_user('test2').person; p2.categories << @category | |
121 | + recent = @finder.recent('people', 1) | |
122 | + assert_includes recent, p2 | |
123 | + assert_not_includes recent, p1 | |
124 | + end | |
125 | + | |
126 | + should 'list recent articles' do | |
127 | + person = create_user('teste').person | |
128 | + art1 = person.articles.build(:name => 'an article to be found'); art1.categories << @category; art1.save! | |
129 | + | |
130 | + art2 = person.articles.build(:name => 'another article to be found'); art2.categories << @category; art2.save! | |
131 | + | |
132 | + result = @finder.recent('articles', 1) | |
133 | + assert_includes result, art2 | |
134 | + assert_not_includes result, art1 | |
135 | + end | |
136 | + | |
137 | + should 'not return the same result twice' do | |
138 | + parent = Category.create!(:name => 'parent category', :environment => Environment.default) | |
139 | + child = Category.create!(:name => 'child category', :environment => Environment.default, :parent => parent) | |
140 | + p1 = create_user('people_1').person; p1.name = 'a beautiful person'; p1.categories << child; p1.save! | |
141 | + p1.categories << parent; p1.save! | |
142 | + | |
143 | + f = CategoryFinder.new(parent) | |
144 | + result = f.people | |
145 | + assert_equal 1, result.size | |
146 | + end | |
147 | + | |
148 | + should 'return most commented articles' do | |
149 | + Article.delete_all | |
150 | + | |
151 | + person = create_user('testuser').person | |
152 | + articles = (1..4).map {|n| a = person.articles.build(:name => "art #{n}", :categories => [@category]); a.save!; a } | |
153 | + | |
154 | + 2.times { articles[0].comments.build(:title => 'test', :body => 'asdsad', :author => person).save! } | |
155 | + 4.times { articles[1].comments.build(:title => 'test', :body => 'asdsad', :author => person).save! } | |
156 | + | |
157 | + # should respect the order (more commented comes first) | |
158 | + assert_equal [articles[1], articles[0]], @finder.most_commented_articles(2) | |
159 | + end | |
117 | 160 | end | ... | ... |