Commit d2e3b9ec048d4f8eaac95b5efc041458b894261e

Authored by Rodrigo Souto
1 parent 5cac53de

Search controller plugin test done

app/controllers/application_controller.rb
@@ -154,20 +154,21 @@ class ApplicationController < ActionController::Base @@ -154,20 +154,21 @@ class ApplicationController < ActionController::Base
154 end 154 end
155 end 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 scope = scope.send(options[:filter]) if options[:filter] 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 end 162 end
164 163
165 private 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 conditions = fields.map do |field| 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 end.join(' OR ') 172 end.join(' OR ')
172 {:results => scope.where(conditions).paginate(paginate_options)} 173 {:results => scope.where(conditions).paginate(paginate_options)}
173 end 174 end
app/controllers/public/search_controller.rb
@@ -211,7 +211,7 @@ class SearchController < PublicController @@ -211,7 +211,7 @@ class SearchController < PublicController
211 end 211 end
212 212
213 def full_text_search 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 end 215 end
216 216
217 private 217 private
lib/noosfero/plugin.rb
@@ -355,7 +355,7 @@ class Noosfero::Plugin @@ -355,7 +355,7 @@ class Noosfero::Plugin
355 # returns = {:results => [a, b, c, ...], ...} 355 # returns = {:results => [a, b, c, ...], ...}
356 # P.S.: The plugin might add other informations on the return hash for its 356 # P.S.: The plugin might add other informations on the return hash for its
357 # own use in specific views 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 end 359 end
360 360
361 def method_missing(method, *args, &block) 361 def method_missing(method, *args, &block)
plugins/solr/lib/solr_plugin.rb
@@ -20,11 +20,15 @@ class SolrPlugin < Noosfero::Plugin @@ -20,11 +20,15 @@ class SolrPlugin < Noosfero::Plugin
20 true 20 true
21 end 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 category = options.delete(:category) 25 category = options.delete(:category)
25 filter = options.delete(:filter) 26 filter = options.delete(:filter)
  27 +
  28 + return if empty_query?(query, category) && klass != Product
  29 +
26 solr_options = solr_options(class_asset(klass), category) 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 solr_options.merge!(products_options(user)) if klass == Product && empty_query?(query, category) 32 solr_options.merge!(products_options(user)) if klass == Product && empty_query?(query, category)
29 klass.find_by_contents(query, paginate_options, solr_options.merge(options)) 33 klass.find_by_contents(query, paginate_options, solr_options.merge(options))
30 end 34 end
plugins/solr/lib/solr_plugin/search_helper.rb
@@ -45,15 +45,11 @@ module SolrPlugin::SearchHelper @@ -45,15 +45,11 @@ module SolrPlugin::SearchHelper
45 def asset_table(asset) 45 def asset_table(asset)
46 asset_class(asset).table_name 46 asset_class(asset).table_name
47 end 47 end
48 -#  
49 -# def multiple_search?  
50 -# ['index', 'category_index'].include?(context.params[:action])  
51 -# end  
52 48
53 def filters(asset) 49 def filters(asset)
54 case asset 50 case asset
55 when :products 51 when :products
56 - ['solr_plugin_public:true'] 52 + ['solr_plugin_public:true', 'enabled:true']
57 when :events 53 when :events
58 [] 54 []
59 else 55 else
@@ -69,6 +65,24 @@ module SolrPlugin::SearchHelper @@ -69,6 +65,24 @@ module SolrPlugin::SearchHelper
69 category.nil? && query.blank? 65 category.nil? && query.blank?
70 end 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 def solr_options(asset, category) 86 def solr_options(asset, category)
73 asset_class = asset_class(asset) 87 asset_class = asset_class(asset)
74 solr_options = {} 88 solr_options = {}
@@ -95,21 +109,6 @@ module SolrPlugin::SearchHelper @@ -95,21 +109,6 @@ module SolrPlugin::SearchHelper
95 solr_options 109 solr_options
96 end 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 def asset_class(asset) 112 def asset_class(asset)
114 asset.to_s.singularize.camelize.constantize 113 asset.to_s.singularize.camelize.constantize
115 end 114 end
plugins/solr/test/functional/search_controller_test.rb
1 require 'test_helper' 1 require 'test_helper'
2 -require 'test_solr_helper' 2 +require File.dirname(__FILE__) + '/../test_solr_helper'
3 require File.dirname(__FILE__) + '/../../lib/ext/facets_browse' 3 require File.dirname(__FILE__) + '/../../lib/ext/facets_browse'
4 4
5 # Re-raise errors caught by the controller. 5 # Re-raise errors caught by the controller.
@@ -108,7 +108,7 @@ class SearchControllerTest < ActionController::TestCase @@ -108,7 +108,7 @@ class SearchControllerTest < ActionController::TestCase
108 prod2 = ent2.products.create!(:name => 'another beautiful product', :product_category => @product_category) 108 prod2 = ent2.products.create!(:name => 'another beautiful product', :product_category => @product_category)
109 109
110 get :products 110 get :products
111 - assert_equivalent [prod2, prod1], assigns(:searches)[:products][:results] 111 + assert_equivalent [prod2, prod1], assigns(:searches)[:products][:results].docs
112 assert_match 'Highlights', @response.body 112 assert_match 'Highlights', @response.body
113 end 113 end
114 114
@@ -156,45 +156,45 @@ class SearchControllerTest < ActionController::TestCase @@ -156,45 +156,45 @@ class SearchControllerTest < ActionController::TestCase
156 end 156 end
157 157
158 # Testing random sequences always have a small chance of failing 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 should 'browse facets when query is not empty' do 199 should 'browse facets when query is not empty' do
200 get :articles, :query => 'something' 200 get :articles, :query => 'something'
plugins/solr/test/test_solr_helper.rb 0 → 100644
@@ -0,0 +1,59 @@ @@ -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,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