Commit 7eb7d4bf799ffde3f9e370f961701a2f1e3471e3

Authored by Braulio Bhavamitra
Committed by Rodrigo Souto
1 parent a3c2ad9b

solr_plugin: Convert scopes to solr filters

app/controllers/application_controller.rb
... ... @@ -174,8 +174,6 @@ class ApplicationController < ActionController::Base
174 174 end
175 175  
176 176 def find_by_contents(asset, scope, query, paginate_options={:page => 1}, options={})
177   - scope = scope.send(options[:filter]) if options[:filter]
178   -
179 177 @plugins.dispatch_first(:find_by_contents, asset, scope, query, paginate_options, options) ||
180 178 fallback_find_by_contents(asset, scope, query, paginate_options, options)
181 179 end
... ...
app/controllers/public/search_controller.rb
... ... @@ -214,6 +214,13 @@ class SearchController < PublicController
214 214 @searches[@asset] = find_by_contents(@asset, @scope, @query, paginate_options, {:category => @category, :filter => @filter})
215 215 end
216 216  
  217 + def find_by_contents asset, scope, query, paginate_options={:page => 1}, options={}
  218 + # only apply fitlers to empty query, sorting is engine specific
  219 + scope = scope.send(options[:filter]) if options[:filter] and @empty_query
  220 +
  221 + super asset, scope, query, paginate_options, options
  222 + end
  223 +
217 224 private
218 225  
219 226 def visible_profiles(klass, *extra_relations)
... ...
plugins/solr/lib/ext/article.rb
... ... @@ -24,7 +24,8 @@ class Article
24 24 {:slug => :text}, {:body => :text},
25 25 {:abstract => :text}, {:filename => :text},
26 26 # filtered fields
27   - {:solr_plugin_public => :boolean}, {:environment_id => :integer},
  27 + {:solr_plugin_public => :boolean}, {:published => :boolean},
  28 + {:environment_id => :integer},
28 29 {:profile_id => :integer}, :language,
29 30 {:solr_plugin_category_filter => :integer},
30 31 # ordered/query-boosted fields
... ...
plugins/solr/lib/ext/profile.rb
... ... @@ -28,7 +28,7 @@ class Profile
28 28 {:solr_plugin_category_filter => :integer},
29 29 # ordered/query-boosted fields
30 30 {:solr_plugin_name_sortable => :string}, {:user_id => :integer},
31   - :enabled, :active, :validated, :public_profile,
  31 + :enabled, :active, :validated, :public_profile, :visible,
32 32 {:lat => :float}, {:lng => :float},
33 33 :updated_at, :created_at,
34 34 ],
... ...
plugins/solr/lib/solr_plugin.rb
... ... @@ -18,16 +18,69 @@ class SolrPlugin < Noosfero::Plugin
18 18 true
19 19 end
20 20  
  21 + def solr_search? empty_query, klass
  22 + not empty_query or klass == Product
  23 + end
  24 +
21 25 def find_by_contents(asset, scope, query, paginate_options={}, options={})
22 26 klass = asset_class(asset)
23   - category = options.delete(:category)
24   - filter = options.delete(:filter)
  27 + category = options[:category]
  28 + empty_query = empty_query? query, category
25 29  
26   - return if empty_query?(query, category) && klass != Product
  30 + return unless solr_search? empty_query, klass
27 31  
28 32 solr_options = solr_options(class_asset(klass), category)
29   - solr_options.merge!(products_options(user)) if klass == Product && empty_query?(query, category)
30   - klass.find_by_contents(query, paginate_options, solr_options.merge(options))
  33 + solr_options[:filter_queries] ||= []
  34 + solr_options[:filter_queries] += scopes_to_solr_filters scope, klass, options
  35 + solr_options.merge! products_options(user) if klass == Product and empty_query
  36 + solr_options.merge! options.except(:category, :filter)
  37 +
  38 + scope.find_by_contents query, paginate_options, solr_options
  39 + end
  40 +
  41 + protected
  42 +
  43 + def scopes_to_solr_filters scope, klass = nil, options = {}
  44 + filter_queries = []
  45 + klass ||= scope.base_class
  46 + solr_fields = klass.configuration[:solr_fields].keys
  47 + scopes_applied = scope.scopes_applied.dup rescue [] #rescue association and class direct filtering
  48 +
  49 + scope.current_scoped_methods[:create].each do |attr, value|
  50 + next unless solr_fields.include? attr.to_sym
  51 +
  52 + # if the filter is present here, then prefer it
  53 + scopes_applied.reject!{ |name| name == attr.to_sym }
  54 +
  55 + filter_queries << "#{attr}:#{value}"
  56 + end
  57 +
  58 + scopes_applied.each do |name|
  59 + next if name.to_s == options[:filter].to_s
  60 +
  61 + has_value = name === Hash
  62 + if has_value
  63 + name, args = name.keys.first, name.values.first
  64 + value = args.first
  65 + end
  66 +
  67 + related_field = nil
  68 + related_field = name if solr_fields.include? name
  69 + related_field = "solr_plugin_#{name}" if solr_fields.include? :"solr_plugin_#{name}"
  70 +
  71 + if has_value
  72 + if related_field
  73 + filter_queries << "#{related_field}:#{value}"
  74 + else
  75 + filter_queries << klass.send("solr_filter_#{name}", *args)
  76 + end
  77 + else
  78 + raise "Undeclared solr field for scope #{name}" if related_field.nil?
  79 + filter_queries << "#{related_field}:true"
  80 + end
  81 + end
  82 +
  83 + filter_queries
31 84 end
32 85  
33 86 def method_missing method, *args, &block
... ...
plugins/solr/test/unit/solr_plugin/plugin_test.rb 0 → 100644
... ... @@ -0,0 +1,16 @@
  1 +require "#{File.dirname(__FILE__)}/../../test_helper"
  2 +
  3 +class SolrPlugin::PluginTest < ActiveSupport::TestCase
  4 +
  5 + def setup
  6 + @plugin = SolrPlugin.new
  7 + end
  8 + attr_reader :plugin
  9 +
  10 + should 'convert scopes to solr filters' do
  11 + person = create_user('test').person
  12 + result = plugin.send :scopes_to_solr_filters, person.files.public.published
  13 + assert_equal result, ["profile_id:#{person.id}", "published:'true'", "solr_plugin_public:true"]
  14 + end
  15 +
  16 +end
... ...
vendor/plugins/monkey_patches/named_scope_with_applied_names/init.rb 0 → 100644
... ... @@ -0,0 +1,57 @@
  1 +require_dependency 'active_record/named_scope'
  2 +
  3 +if Rails::VERSION::STRING < "2.3.99"
  4 +
  5 + module ::ActiveRecord
  6 +
  7 + module NamedScope
  8 +
  9 + module ClassMethods
  10 +
  11 + def named_scope_with_applied_names name, options = {}, &block
  12 + named_scope_without_applied_names name, options, &block
  13 +
  14 + name = name.to_sym
  15 + scopes[name] = lambda do |parent_scope, *args|
  16 + scope = Scope.new(parent_scope, case options
  17 + when Hash
  18 + options
  19 + when Proc
  20 + if self.model_name != parent_scope.model_name
  21 + options.bind(parent_scope).call(*args)
  22 + else
  23 + options.call(*args)
  24 + end
  25 + end, &block)
  26 + scope.scope_name = name
  27 + scope
  28 + end
  29 + end
  30 + alias_method_chain :named_scope, :applied_names
  31 + end
  32 +
  33 + class Scope
  34 + attr_accessor :scope_name, :scopes_applied
  35 +
  36 + def initialize_with_applied_names proxy_scope, options, &block
  37 + initialize_without_applied_names proxy_scope, options, &block
  38 + self.scopes_applied ||= []
  39 + self.scopes_applied += proxy_scope.send :scopes_applied if Scope === proxy_scope
  40 +
  41 + # unrelated bugfix: use if instead of unless
  42 + if (Scope === proxy_scope || ActiveRecord::Associations::AssociationCollection === proxy_scope)
  43 + @current_scoped_methods_when_defined = proxy_scope.send(:current_scoped_methods)
  44 + end
  45 + end
  46 + alias_method_chain :initialize, :applied_names
  47 +
  48 + def scope_name= name
  49 + @scope_name = name
  50 + self.scopes_applied << @scope_name
  51 + end
  52 +
  53 + end
  54 +
  55 + end
  56 + end
  57 +end
... ...