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 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'
... ...
plugins/solr/test/test_solr_helper.rb 0 → 100644
... ... @@ -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