Commit d2e3b9ec048d4f8eaac95b5efc041458b894261e
1 parent
5cac53de
Exists in
master
and in
23 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,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' |
| @@ -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 |