Commit d07e3bd16b6055a3ba50703b0b02103d7ea5ffab
1 parent
3e5043a1
Exists in
master
and in
29 other branches
ActionItem509: implemented pagination infrastructure only left put views helpers
git-svn-id: https://svn.colivre.coop.br/svn/noosfero/trunk@2137 3f533792-8f58-4932-b0fe-aaf55b0a4547
Showing
8 changed files
with
87 additions
and
29 deletions
Show diff stats
app/controllers/public/search_controller.rb
... | ... | @@ -89,20 +89,20 @@ class SearchController < ApplicationController |
89 | 89 | def load_product_categories_menu(asset) |
90 | 90 | @results[asset].uniq! |
91 | 91 | @categories_menu = ProductCategory.menu_categories(@product_category, environment).map do |cat| |
92 | - hits = @finder.count(:products, @filtered_query, calculate_find_options(asset, nil, cat, @region, params[:radius])) | |
92 | + hits = @finder.count(:products, @filtered_query, calculate_find_options(asset, nil, nil, cat, @region, params[:radius])) | |
93 | 93 | childs = [] |
94 | 94 | # REFACTOR DUPLICATED CODE inner loop doing the same thing that outter loop |
95 | 95 | childs = cat.children.map do |child| |
96 | - child_hits = @finder.count(:products, @filtered_query, calculate_find_options(asset, nil, child, @region, params[:radius])) | |
96 | + child_hits = @finder.count(:products, @filtered_query, calculate_find_options(asset, nil, nil, child, @region, params[:radius])) | |
97 | 97 | [child, child_hits] |
98 | 98 | end.select{|child, child_hits| child_hits > 0 } |
99 | 99 | [cat, hits, childs] |
100 | 100 | end.select{|cat, hits| hits > 0 } |
101 | 101 | end |
102 | 102 | |
103 | - def calculate_find_options(asset, limit, product_category, region, radius) | |
103 | + def calculate_find_options(asset, limit, page, product_category, region, radius) | |
104 | 104 | |
105 | - result = { :limit => limit, :product_category => product_category} | |
105 | + result = { :product_category => product_category, :per_page => limit, :page => page } | |
106 | 106 | if [:enterprises, :people].include?(asset) && region |
107 | 107 | result.merge!(:within => radius, :region => region.id) |
108 | 108 | end |
... | ... | @@ -110,6 +110,12 @@ class SearchController < ApplicationController |
110 | 110 | result |
111 | 111 | end |
112 | 112 | |
113 | + # limit the number of results per page | |
114 | + # TODO: dont hardcore like this | |
115 | + def limit | |
116 | + 10 | |
117 | + end | |
118 | + | |
113 | 119 | public |
114 | 120 | |
115 | 121 | include SearchHelper |
... | ... | @@ -125,9 +131,6 @@ class SearchController < ApplicationController |
125 | 131 | [ :events, N_('Events') ] |
126 | 132 | ] |
127 | 133 | |
128 | - # TODO don't hardcode like this >:-( | |
129 | - LIST_LIMIT = 10 | |
130 | - | |
131 | 134 | def complete_region |
132 | 135 | # FIXME this logic should be in the model |
133 | 136 | @regions = Region.find(:all, :conditions => [ '(name like ? or name like ?) and lat is not null and lng is not null', '%' + params[:region][:name] + '%', '%' + params[:region][:name].capitalize + '%' ]) |
... | ... | @@ -145,16 +148,11 @@ class SearchController < ApplicationController |
145 | 148 | # how many assets we are searching for? |
146 | 149 | number_of_result_assets = @searching.values.select{|v| v}.size |
147 | 150 | |
148 | - # apply limit when searching for only one type of asset | |
149 | - limit = (number_of_result_assets == 1) ? nil: LIST_LIMIT | |
150 | - # apply limit to all searches | |
151 | -# limit = nil | |
152 | - | |
153 | 151 | @results = {} |
154 | 152 | @names = {} |
155 | 153 | |
156 | 154 | SEARCH_IN.select { |key,description| @searching[key] }.each do |key, description| |
157 | - @results[key] = @finder.find(key, @filtered_query, calculate_find_options(key, limit, @product_category, @region, params[:radius])) | |
155 | + @results[key] = @finder.find(key, @filtered_query, calculate_find_options(key, limit, params[:page], @product_category, @region, params[:radius])) | |
158 | 156 | @names[key] = gettext(description) |
159 | 157 | end |
160 | 158 | ... | ... |
app/models/category_finder.rb
... | ... | @@ -7,8 +7,6 @@ class CategoryFinder |
7 | 7 | |
8 | 8 | attr_reader :category_id |
9 | 9 | |
10 | - | |
11 | - | |
12 | 10 | def find(asset, query='', options={}) |
13 | 11 | @region = Region.find_by_id(options.delete(:region)) if options.has_key?(:region) |
14 | 12 | if @region && options[:within] |
... | ... | @@ -17,10 +15,12 @@ class CategoryFinder |
17 | 15 | options.delete(:within) |
18 | 16 | end |
19 | 17 | |
18 | + options = {:page => 1, :per_page => options.delete(:limit)}.merge(options) | |
20 | 19 | if query.blank? |
21 | - asset_class(asset).find(:all, options_for_find(asset_class(asset), {:order => "created_at desc, #{asset_table(asset)}.id desc"}.merge(options))) | |
20 | + asset_class(asset).paginate(:all, options_for_find(asset_class(asset), {:order => "created_at desc, #{asset_table(asset)}.id desc"}.merge(options))) | |
22 | 21 | else |
23 | - asset_class(asset).find_by_contents(query, {}, options_for_find(asset_class(asset), options)).uniq | |
22 | + ferret_options = {:page => options.delete(:page), :per_page => options.delete(:per_page)} | |
23 | + asset_class(asset).find_by_contents(query, ferret_options, options_for_find(asset_class(asset), options)).uniq | |
24 | 24 | end |
25 | 25 | end |
26 | 26 | |
... | ... | @@ -33,8 +33,10 @@ class CategoryFinder |
33 | 33 | end |
34 | 34 | |
35 | 35 | def count(asset, query='', options={}) |
36 | + # because will_paginate needs a page | |
37 | + options = {:page => 1}.merge(options) | |
36 | 38 | if query.blank? |
37 | - find(asset, query, options).size | |
39 | + find(asset, query, options).total_entries | |
38 | 40 | else |
39 | 41 | find(asset, query, options).total_hits |
40 | 42 | end | ... | ... |
app/models/environment_finder.rb
... | ... | @@ -15,22 +15,25 @@ class EnvironmentFinder |
15 | 15 | product_category = options.delete(:product_category) |
16 | 16 | product_category_ids = product_category.map_traversal(&:id) if product_category |
17 | 17 | |
18 | + options = {:page => 1, :per_page => options.delete(:limit)}.merge(options) | |
18 | 19 | if query.blank? |
19 | - if product_category && asset == :products | |
20 | - @environment.send(asset).find(:all, options.merge({:order => 'created_at desc, id desc', :conditions => ['product_category_id in (?)', product_category_ids]})) | |
21 | - elsif product_category && asset == :enterprises | |
22 | - @environment.send(asset).find(:all, options.merge(:order => 'profiles.created_at desc, profiles.id desc', :include => 'products', :conditions => ['products.product_category_id in (?)', product_category_ids])) | |
23 | - else | |
24 | - @environment.send(asset).find( :all, options.merge( {:order => 'created_at desc, id desc'} ) ) | |
25 | - end | |
20 | + options = {:order => 'created_at desc, id desc'}.merge(options) | |
21 | + if product_category && asset == :products | |
22 | + @environment.send(asset).paginate(:all, options.merge(:conditions => ['product_category_id in (?)', product_category_ids])) | |
23 | + elsif product_category && asset == :enterprises | |
24 | + @environment.send(asset).paginate(:all, options.merge(:order => 'profiles.created_at desc, profiles.id desc', :include => 'products', :conditions => ['products.product_category_id in (?)', product_category_ids])) | |
25 | + else | |
26 | + @environment.send(asset).paginate(:all, options) | |
27 | + end | |
26 | 28 | else |
29 | + ferret_options = {:page => options.delete(:page), :per_page => options.delete(:per_page)} | |
27 | 30 | if product_category && asset == :products |
28 | 31 | # SECURITY no risk of SQL injection, since product_category_ids comes from trusted source |
29 | - @environment.send(asset).find_by_contents(query, {}, options.merge({:conditions => 'product_category_id in (%s)' % product_category_ids.join(',') })) | |
32 | + @environment.send(asset).find_by_contents(query, ferret_options, options.merge({:conditions => 'product_category_id in (%s)' % product_category_ids.join(',') })) | |
30 | 33 | elsif product_category && asset == :enterprises |
31 | - @environment.send(asset).find_by_contents(query + " +extra_data_for_index:#{product_category.name}", {}, options) | |
34 | + @environment.send(asset).find_by_contents(query + " +extra_data_for_index:#{product_category.name}", ferret_options, options) | |
32 | 35 | else |
33 | - @environment.send(asset).find_by_contents(query, {}, options) | |
36 | + @environment.send(asset).find_by_contents(query, ferret_options, options) | |
34 | 37 | end |
35 | 38 | end |
36 | 39 | end |
... | ... | @@ -44,9 +47,11 @@ class EnvironmentFinder |
44 | 47 | end |
45 | 48 | |
46 | 49 | def count(asset, query = '', options = {}) |
50 | + # because will_paginate needs a page | |
51 | + options = {:page => 1}.merge(options) | |
47 | 52 | if query.blank? |
48 | 53 | # SLOW |
49 | - find(asset, query, options).size | |
54 | + find(asset, query, options).total_entries | |
50 | 55 | else |
51 | 56 | find(asset, query, options).total_hits |
52 | 57 | end | ... | ... |
app/views/search/products.rhtml
config/environment.rb
... | ... | @@ -103,6 +103,7 @@ require 'acts_as_having_settings' |
103 | 103 | require 'acts_as_having_image' |
104 | 104 | require 'hacked_after_create' |
105 | 105 | require 'sqlite_extension' |
106 | +require 'will_paginate' | |
106 | 107 | |
107 | 108 | # load a local configuration if present, but not under test environment. |
108 | 109 | if ENV['RAILS_ENV'] != 'test' | ... | ... |
test/functional/search_controller_test.rb
... | ... | @@ -283,6 +283,16 @@ class SearchControllerTest < Test::Unit::TestCase |
283 | 283 | assert_equal [prod1], assigns(:results)[:products] |
284 | 284 | end |
285 | 285 | |
286 | + should 'paginate enterprise listing' do | |
287 | + @controller.expects(:limit).returns(1) | |
288 | + ent1 = Enterprise.create!(:name => 'teste 1', :identifier => 'teste_1') | |
289 | + ent2 = Enterprise.create!(:name => 'teste 2', :identifier => 'teste_2') | |
290 | + | |
291 | + get :assets, :asset => 'enterprises', :page => '2' | |
292 | + | |
293 | + assert_equal [ent1], assigns(:results)[:enterprises] # older on page 2 | |
294 | + end | |
295 | + | |
286 | 296 | should 'display search results' do |
287 | 297 | ent = Enterprise.create!(:name => 'display enterprise', :identifier => 'teste1') |
288 | 298 | product = ent.products.create!(:name => 'display product') | ... | ... |
test/unit/category_finder_test.rb
... | ... | @@ -151,6 +151,24 @@ class CategoryFinderTest < ActiveSupport::TestCase |
151 | 151 | assert_includes recent, ent2 |
152 | 152 | assert_not_includes recent, ent1 |
153 | 153 | end |
154 | + | |
155 | + should 'paginate the list of more enterprises than limit' do | |
156 | + ent1 = Enterprise.create!(:name => 'teste1', :identifier => 'teste1', :category_ids => [@category.id]) | |
157 | + ent2 = Enterprise.create!(:name => 'teste2', :identifier => 'teste2', :category_ids => [@category.id]) | |
158 | + | |
159 | + assert_equal [ent2], @finder.find('enterprises', nil, :per_page => 1, :page => 1) | |
160 | + assert_equal [ent1], @finder.find('enterprises', nil, :per_page => 1, :page => 2) | |
161 | + end | |
162 | + | |
163 | + should 'paginate the list of more enterprises than limit with query' do | |
164 | + ent1 = Enterprise.create!(:name => 'teste 1', :identifier => 'teste1', :category_ids => [@category.id]) | |
165 | + ent2 = Enterprise.create!(:name => 'teste 2', :identifier => 'teste2', :category_ids => [@category.id]) | |
166 | + | |
167 | + p1 = @finder.find('enterprises', 'teste', :per_page => 1, :page => 1) | |
168 | + p2 = @finder.find('enterprises', 'teste', :per_page => 1, :page => 2) | |
169 | + | |
170 | + assert (p1 == [ent1] && p2 == [ent2]) || (p1 == [ent2] && p2 == [ent1]) # consistent paging | |
171 | + end | |
154 | 172 | |
155 | 173 | should 'count enterprises' do |
156 | 174 | count = @finder.count('enterprises') | ... | ... |
test/unit/environment_finder_test.rb
... | ... | @@ -49,6 +49,27 @@ class EnvironmentFinderTest < ActiveSupport::TestCase |
49 | 49 | recent = finder.recent('enterprises', 1) |
50 | 50 | assert_includes recent, ent2 # newer |
51 | 51 | assert_not_includes recent, ent1 # older |
52 | + end | |
53 | + | |
54 | + should 'paginate the list of more enterprises than limit' do | |
55 | + finder = EnvironmentFinder.new(Environment.default) | |
56 | + ent1 = Enterprise.create!(:name => 'teste1', :identifier => 'teste1') | |
57 | + ent2 = Enterprise.create!(:name => 'teste2', :identifier => 'teste2') | |
58 | + | |
59 | + assert_equal [ent2], finder.find('enterprises', nil, :per_page => 1, :page => 1) #newer | |
60 | + assert_equal [ent1], finder.find('enterprises', nil, :per_page => 1, :page => 2) #older | |
61 | + end | |
62 | + | |
63 | + should 'paginate the list of more enterprises than limit with query' do | |
64 | + finder = EnvironmentFinder.new(Environment.default) | |
65 | + | |
66 | + ent1 = Enterprise.create!(:name => 'teste 1', :identifier => 'teste1') | |
67 | + ent2 = Enterprise.create!(:name => 'teste 2', :identifier => 'teste2') | |
68 | + | |
69 | + p1 = finder.find('enterprises', 'teste', :per_page => 1, :page => 1) | |
70 | + p2 = finder.find('enterprises', 'teste', :per_page => 1, :page => 2) | |
71 | + | |
72 | + assert (p1 == [ent1] && p2 == [ent2]) || (p1 == [ent2] && p2 == [ent1]) | |
52 | 73 | end |
53 | 74 | |
54 | 75 | should 'count enterprises' do |
... | ... | @@ -57,6 +78,7 @@ class EnvironmentFinderTest < ActiveSupport::TestCase |
57 | 78 | Enterprise.create!(:name => 'teste1', :identifier => 'teste1') |
58 | 79 | assert_equal count+1, finder.count('enterprises') |
59 | 80 | end |
81 | + | |
60 | 82 | should 'count people' do |
61 | 83 | finder = EnvironmentFinder.new(Environment.default) |
62 | 84 | count = finder.count('people') | ... | ... |