Commit cc17d60a3936837afdc7a2dfcefe51acbe27eb5f
1 parent
cdde5e0b
Exists in
master
and in
23 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 | ... | ... |