Commit 7eb7d4bf799ffde3f9e370f961701a2f1e3471e3
Committed by
Rodrigo Souto
1 parent
a3c2ad9b
Exists in
master
and in
28 other branches
solr_plugin: Convert scopes to solr filters
Showing
7 changed files
with
141 additions
and
9 deletions
Show diff stats
app/controllers/application_controller.rb
@@ -174,8 +174,6 @@ class ApplicationController < ActionController::Base | @@ -174,8 +174,6 @@ class ApplicationController < ActionController::Base | ||
174 | end | 174 | end |
175 | 175 | ||
176 | def find_by_contents(asset, scope, query, paginate_options={:page => 1}, options={}) | 176 | def find_by_contents(asset, scope, query, paginate_options={:page => 1}, options={}) |
177 | - scope = scope.send(options[:filter]) if options[:filter] | ||
178 | - | ||
179 | @plugins.dispatch_first(:find_by_contents, asset, scope, query, paginate_options, options) || | 177 | @plugins.dispatch_first(:find_by_contents, asset, scope, query, paginate_options, options) || |
180 | fallback_find_by_contents(asset, scope, query, paginate_options, options) | 178 | fallback_find_by_contents(asset, scope, query, paginate_options, options) |
181 | end | 179 | end |
app/controllers/public/search_controller.rb
@@ -214,6 +214,13 @@ class SearchController < PublicController | @@ -214,6 +214,13 @@ class SearchController < PublicController | ||
214 | @searches[@asset] = find_by_contents(@asset, @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 | + 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 | private | 224 | private |
218 | 225 | ||
219 | def visible_profiles(klass, *extra_relations) | 226 | def visible_profiles(klass, *extra_relations) |
plugins/solr/lib/ext/article.rb
@@ -24,7 +24,8 @@ class Article | @@ -24,7 +24,8 @@ class Article | ||
24 | {:slug => :text}, {:body => :text}, | 24 | {:slug => :text}, {:body => :text}, |
25 | {:abstract => :text}, {:filename => :text}, | 25 | {:abstract => :text}, {:filename => :text}, |
26 | # filtered fields | 26 | # filtered fields |
27 | - {:solr_plugin_public => :boolean}, {:environment_id => :integer}, | 27 | + {:solr_plugin_public => :boolean}, {:published => :boolean}, |
28 | + {:environment_id => :integer}, | ||
28 | {:profile_id => :integer}, :language, | 29 | {:profile_id => :integer}, :language, |
29 | {:solr_plugin_category_filter => :integer}, | 30 | {:solr_plugin_category_filter => :integer}, |
30 | # ordered/query-boosted fields | 31 | # ordered/query-boosted fields |
plugins/solr/lib/ext/profile.rb
@@ -28,7 +28,7 @@ class Profile | @@ -28,7 +28,7 @@ class Profile | ||
28 | {:solr_plugin_category_filter => :integer}, | 28 | {:solr_plugin_category_filter => :integer}, |
29 | # ordered/query-boosted fields | 29 | # ordered/query-boosted fields |
30 | {:solr_plugin_name_sortable => :string}, {:user_id => :integer}, | 30 | {:solr_plugin_name_sortable => :string}, {:user_id => :integer}, |
31 | - :enabled, :active, :validated, :public_profile, | 31 | + :enabled, :active, :validated, :public_profile, :visible, |
32 | {:lat => :float}, {:lng => :float}, | 32 | {:lat => :float}, {:lng => :float}, |
33 | :updated_at, :created_at, | 33 | :updated_at, :created_at, |
34 | ], | 34 | ], |
plugins/solr/lib/solr_plugin.rb
@@ -18,16 +18,69 @@ class SolrPlugin < Noosfero::Plugin | @@ -18,16 +18,69 @@ class SolrPlugin < Noosfero::Plugin | ||
18 | true | 18 | true |
19 | end | 19 | end |
20 | 20 | ||
21 | + def solr_search? empty_query, klass | ||
22 | + not empty_query or klass == Product | ||
23 | + end | ||
24 | + | ||
21 | def find_by_contents(asset, scope, query, paginate_options={}, options={}) | 25 | def find_by_contents(asset, scope, query, paginate_options={}, options={}) |
22 | klass = asset_class(asset) | 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 | solr_options = solr_options(class_asset(klass), category) | 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 | end | 84 | end |
32 | 85 | ||
33 | def method_missing method, *args, &block | 86 | def method_missing method, *args, &block |
@@ -0,0 +1,16 @@ | @@ -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 @@ | @@ -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 |