Commit d2e3b9ec048d4f8eaac95b5efc041458b894261e
1 parent
5cac53de
Exists in
master
and in
29 other branches
Search controller plugin test done
Showing
8 changed files
with
135 additions
and
122 deletions
Show diff stats
app/controllers/application_controller.rb
... | ... | @@ -154,20 +154,21 @@ class ApplicationController < ActionController::Base |
154 | 154 | end |
155 | 155 | end |
156 | 156 | |
157 | - def find_by_contents(scope, query, paginate_options={:page => 1}, options={}) | |
157 | + def find_by_contents(asset, scope, query, paginate_options={:page => 1}, options={}) | |
158 | 158 | scope = scope.send(options[:filter]) if options[:filter] |
159 | - return {:results => scope.paginate(paginate_options)} if query.blank? | |
160 | 159 | |
161 | - @plugins.first(:find_by_contents, scope, query, paginate_options, options) || | |
162 | - fallback_find_by_contents(scope, query, paginate_options, options) | |
160 | + @plugins.first(:find_by_contents, asset, scope, query, paginate_options, options) || | |
161 | + fallback_find_by_contents(asset, scope, query, paginate_options, options) | |
163 | 162 | end |
164 | 163 | |
165 | 164 | private |
166 | 165 | |
167 | - def fallback_find_by_contents(scope, query, paginate_options, options) | |
168 | - fields = scope.base_class::SEARCHABLE_FIELDS.keys.map(&:to_s) & scope.base_class.column_names | |
166 | + def fallback_find_by_contents(asset, scope, query, paginate_options, options) | |
167 | + return {:results => scope.paginate(paginate_options)} if query.blank? | |
168 | + klass = asset.to_s.singularize.camelize.constantize | |
169 | + fields = klass::SEARCHABLE_FIELDS.keys.map(&:to_s) & klass.column_names | |
169 | 170 | conditions = fields.map do |field| |
170 | - "lower(#{scope.base_class.table_name}.#{field}) LIKE \"%#{query.downcase.strip}%\"" | |
171 | + "lower(#{klass.table_name}.#{field}) LIKE \"%#{query.downcase.strip}%\"" | |
171 | 172 | end.join(' OR ') |
172 | 173 | {:results => scope.where(conditions).paginate(paginate_options)} |
173 | 174 | end | ... | ... |
app/controllers/public/search_controller.rb
... | ... | @@ -211,7 +211,7 @@ class SearchController < PublicController |
211 | 211 | end |
212 | 212 | |
213 | 213 | def full_text_search |
214 | - @searches[@asset] = find_by_contents(@scope, @query, paginate_options, {:category => @category, :filter => @filter}) | |
214 | + @searches[@asset] = find_by_contents(@asset, @scope, @query, paginate_options, {:category => @category, :filter => @filter}) | |
215 | 215 | end |
216 | 216 | |
217 | 217 | private | ... | ... |
lib/noosfero/plugin.rb
... | ... | @@ -355,7 +355,7 @@ class Noosfero::Plugin |
355 | 355 | # returns = {:results => [a, b, c, ...], ...} |
356 | 356 | # P.S.: The plugin might add other informations on the return hash for its |
357 | 357 | # own use in specific views |
358 | - def find_by_contents(klass, query, paginate_options={}, options={}) | |
358 | + def find_by_contents(asset, klass, query, paginate_options={}, options={}) | |
359 | 359 | end |
360 | 360 | |
361 | 361 | def method_missing(method, *args, &block) | ... | ... |
plugins/solr/lib/solr_plugin.rb
... | ... | @@ -20,11 +20,15 @@ class SolrPlugin < Noosfero::Plugin |
20 | 20 | true |
21 | 21 | end |
22 | 22 | |
23 | - def find_by_contents(klass, query, paginate_options={}, options={}) | |
23 | + def find_by_contents(asset, scope, query, paginate_options={}, options={}) | |
24 | + klass = asset_class(asset) | |
24 | 25 | category = options.delete(:category) |
25 | 26 | filter = options.delete(:filter) |
27 | + | |
28 | + return if empty_query?(query, category) && klass != Product | |
29 | + | |
26 | 30 | solr_options = solr_options(class_asset(klass), category) |
27 | - user = context.respond_to?(:user) ? context.send(:user) : nil | |
31 | + user = context.send(:logged_in?) ? context.send(:user) : nil | |
28 | 32 | solr_options.merge!(products_options(user)) if klass == Product && empty_query?(query, category) |
29 | 33 | klass.find_by_contents(query, paginate_options, solr_options.merge(options)) |
30 | 34 | end | ... | ... |
plugins/solr/lib/solr_plugin/search_helper.rb
... | ... | @@ -45,15 +45,11 @@ module SolrPlugin::SearchHelper |
45 | 45 | def asset_table(asset) |
46 | 46 | asset_class(asset).table_name |
47 | 47 | end |
48 | -# | |
49 | -# def multiple_search? | |
50 | -# ['index', 'category_index'].include?(context.params[:action]) | |
51 | -# end | |
52 | 48 | |
53 | 49 | def filters(asset) |
54 | 50 | case asset |
55 | 51 | when :products |
56 | - ['solr_plugin_public:true'] | |
52 | + ['solr_plugin_public:true', 'enabled:true'] | |
57 | 53 | when :events |
58 | 54 | [] |
59 | 55 | else |
... | ... | @@ -69,6 +65,24 @@ module SolrPlugin::SearchHelper |
69 | 65 | category.nil? && query.blank? |
70 | 66 | end |
71 | 67 | |
68 | + def products_options(person) | |
69 | + geosearch = person && person.lat && person.lng | |
70 | + | |
71 | + extra_limit = LIST_SEARCH_LIMIT*5 | |
72 | + sql_options = {:limit => LIST_SEARCH_LIMIT, :order => 'random()'} | |
73 | + options = {:sql_options => sql_options, :extra_limit => extra_limit} | |
74 | + | |
75 | + if geosearch | |
76 | + options.merge({ | |
77 | + :alternate_query => "{!boost b=recip(geodist(),#{"%e" % (1.to_f/DistBoost)},1,1)}", | |
78 | + :radius => DistFilt, | |
79 | + :latitude => person.lat, | |
80 | + :longitude => person.lng }) | |
81 | + else | |
82 | + options.merge({:boost_functions => ['recip(ms(NOW/HOUR,updated_at),1.3e-10,1,1)']}) | |
83 | + end | |
84 | + end | |
85 | + | |
72 | 86 | def solr_options(asset, category) |
73 | 87 | asset_class = asset_class(asset) |
74 | 88 | solr_options = {} |
... | ... | @@ -95,21 +109,6 @@ module SolrPlugin::SearchHelper |
95 | 109 | solr_options |
96 | 110 | end |
97 | 111 | |
98 | - def products_options(person) | |
99 | - geosearch = person && person.lat && person.lng | |
100 | - | |
101 | - extra_limit = LIST_SEARCH_LIMIT*5 | |
102 | - sql_options = {:limit => LIST_SEARCH_LIMIT, :order => 'random()'} | |
103 | - if geosearch | |
104 | - {:sql_options => sql_options, :extra_limit => extra_limit, | |
105 | - :alternate_query => "{!boost b=recip(geodist(),#{"%e" % (1.to_f/DistBoost)},1,1)}", | |
106 | - :radius => DistFilt, :latitude => person.lat, :longitude => person.lng} | |
107 | - else | |
108 | - { :sql_options => sql_options, :extra_limit => extra_limit, | |
109 | - :boost_functions => ['recip(ms(NOW/HOUR,updated_at),1.3e-10,1,1)']} | |
110 | - end | |
111 | - end | |
112 | - | |
113 | 112 | def asset_class(asset) |
114 | 113 | asset.to_s.singularize.camelize.constantize |
115 | 114 | end | ... | ... |
plugins/solr/test/functional/search_controller_test.rb
1 | 1 | require 'test_helper' |
2 | -require 'test_solr_helper' | |
2 | +require File.dirname(__FILE__) + '/../test_solr_helper' | |
3 | 3 | require File.dirname(__FILE__) + '/../../lib/ext/facets_browse' |
4 | 4 | |
5 | 5 | # Re-raise errors caught by the controller. |
... | ... | @@ -108,7 +108,7 @@ class SearchControllerTest < ActionController::TestCase |
108 | 108 | prod2 = ent2.products.create!(:name => 'another beautiful product', :product_category => @product_category) |
109 | 109 | |
110 | 110 | get :products |
111 | - assert_equivalent [prod2, prod1], assigns(:searches)[:products][:results] | |
111 | + assert_equivalent [prod2, prod1], assigns(:searches)[:products][:results].docs | |
112 | 112 | assert_match 'Highlights', @response.body |
113 | 113 | end |
114 | 114 | |
... | ... | @@ -156,45 +156,45 @@ class SearchControllerTest < ActionController::TestCase |
156 | 156 | end |
157 | 157 | |
158 | 158 | # Testing random sequences always have a small chance of failing |
159 | -# should 'randomize product display in empty search' do | |
160 | -# prod_cat = ProductCategory.create!(:name => 'prod cat test', :environment => Environment.default) | |
161 | -# ent = create_profile_with_optional_category(Enterprise, 'test enterprise') | |
162 | -# (1..SearchController::LIST_SEARCH_LIMIT+5).each do |n| | |
163 | -# fast_create(Product, {:name => "produto #{n}", :enterprise_id => ent.id, :product_category_id => prod_cat.id}, :search => true) | |
164 | -# end | |
165 | -# | |
166 | -# get :products | |
167 | -# result1 = assigns(:searches)[:products][:results].map(&:id) | |
168 | -# | |
169 | -# (1..10).each do |n| | |
170 | -# get :products | |
171 | -# end | |
172 | -# result2 = assigns(:searches)[:products][:results].map(&:id) | |
173 | -# | |
174 | -# assert_not_equal result1, result2 | |
175 | -# end | |
176 | -# | |
177 | -# should 'remove far products by geolocalization empty logged search' do | |
178 | -# user = create_user('a_logged_user') | |
179 | -# # trigger geosearch | |
180 | -# user.person.lat = '1.0' | |
181 | -# user.person.lng = '1.0' | |
182 | -# SearchController.any_instance.stubs(:logged_in?).returns(true) | |
183 | -# SearchController.any_instance.stubs(:current_user).returns(user) | |
184 | -# | |
185 | -# cat = fast_create(ProductCategory) | |
186 | -# ent1 = Enterprise.create!(:name => 'ent1', :identifier => 'ent1', :lat => '1.3', :lng => '1.3') | |
187 | -# prod1 = Product.create!(:name => 'produto 1', :enterprise_id => ent1.id, :product_category_id => cat.id) | |
188 | -# ent2 = Enterprise.create!(:name => 'ent2', :identifier => 'ent2', :lat => '2.0', :lng => '2.0') | |
189 | -# prod2 = Product.create!(:name => 'produto 2', :enterprise_id => ent2.id, :product_category_id => cat.id) | |
190 | -# ent3 = Enterprise.create!(:name => 'ent3', :identifier => 'ent3', :lat => '1.6', :lng => '1.6') | |
191 | -# prod3 = Product.create!(:name => 'produto 3', :enterprise_id => ent3.id, :product_category_id => cat.id) | |
192 | -# ent4 = Enterprise.create!(:name => 'ent4', :identifier => 'ent4', :lat => '10', :lng => '10') | |
193 | -# prod4 = Product.create!(:name => 'produto 4', :enterprise_id => ent4.id, :product_category_id => cat.id) | |
194 | -# | |
195 | -# get :products | |
196 | -# assert_equivalent [prod1, prod3, prod2], assigns(:searches)[:products][:results] | |
197 | -# end | |
159 | + should 'randomize product display in empty search' do | |
160 | + prod_cat = ProductCategory.create!(:name => 'prod cat test', :environment => Environment.default) | |
161 | + ent = create_profile_with_optional_category(Enterprise, 'test enterprise') | |
162 | + (1..SearchController::LIST_SEARCH_LIMIT+5).each do |n| | |
163 | + fast_create(Product, {:name => "produto #{n}", :enterprise_id => ent.id, :product_category_id => prod_cat.id}, :search => true) | |
164 | + end | |
165 | + | |
166 | + get :products | |
167 | + result1 = assigns(:searches)[:products][:results].map(&:id) | |
168 | + | |
169 | + (1..10).each do |n| | |
170 | + get :products | |
171 | + end | |
172 | + result2 = assigns(:searches)[:products][:results].map(&:id) | |
173 | + | |
174 | + assert_not_equal result1, result2 | |
175 | + end | |
176 | + | |
177 | + should 'remove far products by geolocalization empty logged search' do | |
178 | + user = create_user('a_logged_user') | |
179 | + # trigger geosearch | |
180 | + user.person.lat = '1.0' | |
181 | + user.person.lng = '1.0' | |
182 | + SearchController.any_instance.stubs(:logged_in?).returns(true) | |
183 | + SearchController.any_instance.stubs(:current_user).returns(user) | |
184 | + | |
185 | + cat = fast_create(ProductCategory) | |
186 | + ent1 = Enterprise.create!(:name => 'ent1', :identifier => 'ent1', :lat => '1.3', :lng => '1.3') | |
187 | + prod1 = Product.create!(:name => 'produto 1', :enterprise_id => ent1.id, :product_category_id => cat.id) | |
188 | + ent2 = Enterprise.create!(:name => 'ent2', :identifier => 'ent2', :lat => '2.0', :lng => '2.0') | |
189 | + prod2 = Product.create!(:name => 'produto 2', :enterprise_id => ent2.id, :product_category_id => cat.id) | |
190 | + ent3 = Enterprise.create!(:name => 'ent3', :identifier => 'ent3', :lat => '1.6', :lng => '1.6') | |
191 | + prod3 = Product.create!(:name => 'produto 3', :enterprise_id => ent3.id, :product_category_id => cat.id) | |
192 | + ent4 = Enterprise.create!(:name => 'ent4', :identifier => 'ent4', :lat => '10', :lng => '10') | |
193 | + prod4 = Product.create!(:name => 'produto 4', :enterprise_id => ent4.id, :product_category_id => cat.id) | |
194 | + | |
195 | + get :products | |
196 | + assert_equivalent [prod1, prod3, prod2], assigns(:searches)[:products][:results].docs | |
197 | + end | |
198 | 198 | |
199 | 199 | should 'browse facets when query is not empty' do |
200 | 200 | get :articles, :query => 'something' | ... | ... |
... | ... | @@ -0,0 +1,59 @@ |
1 | +class ActsAsSolr::Post | |
2 | + class << self | |
3 | + alias_method :execute_orig, :execute | |
4 | + end | |
5 | +end | |
6 | +module ActsAsSolr::ParserMethods | |
7 | + alias_method :parse_results_orig, :parse_results | |
8 | +end | |
9 | + | |
10 | +class TestSolr | |
11 | + | |
12 | + def self.enable | |
13 | + ActsAsSolr::Post.class_eval do | |
14 | + def self.execute(*args) | |
15 | + execute_orig *args | |
16 | + end | |
17 | + end | |
18 | + ActsAsSolr::ParserMethods.module_eval do | |
19 | + def parse_results(*args) | |
20 | + parse_results_orig *args | |
21 | + end | |
22 | + end | |
23 | + | |
24 | + # clear index | |
25 | + ActsAsSolr::Post.execute(Solr::Request::Delete.new(:query => '*:*')) | |
26 | + | |
27 | + @solr_disabled = false | |
28 | + end | |
29 | + | |
30 | + def self.disable | |
31 | + return if @solr_disabled | |
32 | + | |
33 | + ActsAsSolr::Post.class_eval do | |
34 | + def self.execute(*args) | |
35 | + true | |
36 | + end | |
37 | + end | |
38 | + ActsAsSolr::ParserMethods.module_eval do | |
39 | + def parse_results(*args) | |
40 | + parse_results_orig nil, args[1] | |
41 | + end | |
42 | + end | |
43 | + | |
44 | + @solr_disabled = true | |
45 | + end | |
46 | + | |
47 | +end | |
48 | + | |
49 | +class ActiveSupport::TestCase | |
50 | + def fast_create_with_solr(name, attrs = {}, options = {}) | |
51 | + obj = fast_create_without_solr(name, attrs, options) | |
52 | + obj.solr_save if options[:search] | |
53 | + obj | |
54 | + end | |
55 | + alias_method_chain :fast_create, :solr | |
56 | +end | |
57 | + | |
58 | +# disable solr actions by default | |
59 | +TestSolr.disable | ... | ... |
test/test_solr_helper.rb
... | ... | @@ -1,50 +0,0 @@ |
1 | -class ActsAsSolr::Post | |
2 | - class << self | |
3 | - alias_method :execute_orig, :execute | |
4 | - end | |
5 | -end | |
6 | -module ActsAsSolr::ParserMethods | |
7 | - alias_method :parse_results_orig, :parse_results | |
8 | -end | |
9 | - | |
10 | -class TestSolr | |
11 | - | |
12 | - def self.enable | |
13 | - ActsAsSolr::Post.class_eval do | |
14 | - def self.execute(*args) | |
15 | - execute_orig *args | |
16 | - end | |
17 | - end | |
18 | - ActsAsSolr::ParserMethods.module_eval do | |
19 | - def parse_results(*args) | |
20 | - parse_results_orig *args | |
21 | - end | |
22 | - end | |
23 | - | |
24 | - # clear index | |
25 | - ActsAsSolr::Post.execute(Solr::Request::Delete.new(:query => '*:*')) | |
26 | - | |
27 | - @solr_disabled = false | |
28 | - end | |
29 | - | |
30 | - def self.disable | |
31 | - return if @solr_disabled | |
32 | - | |
33 | - ActsAsSolr::Post.class_eval do | |
34 | - def self.execute(*args) | |
35 | - true | |
36 | - end | |
37 | - end | |
38 | - ActsAsSolr::ParserMethods.module_eval do | |
39 | - def parse_results(*args) | |
40 | - parse_results_orig nil, args[1] | |
41 | - end | |
42 | - end | |
43 | - | |
44 | - @solr_disabled = true | |
45 | - end | |
46 | - | |
47 | -end | |
48 | - | |
49 | -# disable solr actions by default | |
50 | -TestSolr.disable |