Module: SearchScope
- Included in:
- ActiveRecord::Base
- Defined in:
- lib/search_scope.rb
Defined Under Namespace
Classes: SortScope
Instance Method Summary collapse
- #get_search_scope_from_object(object, scope, *args) ⇒ Object
-
#paginate_search(params = {}) ⇒ Object
this is for use with will_paginate.
-
#quick_search_scope_options(quick_search_terms) ⇒ Object
this gets all of the options from the quick_search named scopes and builds a quick_search from them the quick_search is one that matches any of the named scopes, not all of them.
-
#quick_search_scopes ⇒ Object
for now, we’ll say that by definition, if a search_scope defines a lambda with one term, then it is a quick_search_scope.
-
#search(params = {}) ⇒ Object
this searches by chaining all of the named_scopes (search_scopes) that were included in the params.
- #search_scope(name, options = {}, &block) ⇒ Object
- #search_scope_keys ⇒ Object
- #search_scopes(options = {}) ⇒ Object
- #sort_choices ⇒ Object
- #sort_choices_hash ⇒ Object
- #sort_search_by(name, options = {}) ⇒ Object
- #sort_search_by_options(sort_by) ⇒ Object
Instance Method Details
#get_search_scope_from_object(object, scope, *args) ⇒ Object
84 85 86 87 |
# File 'lib/search_scope.rb', line 84 def get_search_scope_from_object(object, scope, *args) scope_name = "search_#{scope}".intern scope = object.send(scope_name, *args) end |
#paginate_search(params = {}) ⇒ Object
this is for use with will_paginate
148 149 150 151 |
# File 'lib/search_scope.rb', line 148 def paginate_search(params={}) params[:paginate] = true search params end |
#quick_search_scope_options(quick_search_terms) ⇒ Object
this gets all of the options from the quick_search named scopes and builds a quick_search from them the quick_search is one that matches any of the named scopes, not all of them. TODO look into better ways of doing this, and figure out the proper name.
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/search_scope.rb', line 92 def (quick_search_terms) conditions = [] includes = [] aggregate_scope = self quick_search_scopes.each do |scope| term_conditions = [] terms = quick_search_terms.split.compact terms.each_with_index do |term,index| # quick_search_scope = self.send(scope, term) quick_search_scope = get_search_scope_from_object(self, scope, term) = quick_search_scope. term_conditions << self.sanitize_sql_for_conditions([:conditions]) #only do this once, the first time if [:include] && index == 0 includes << [:include] unless includes.include? [:include] end = .keys - [:conditions, :include] raise "search_scope with quick_search does not support the #{.first.inspect} option at this time (#{scope.inspect})" if .first end conditions << term_conditions.collect{|c|"(#{c})"}.join(' OR ') #ORing makes sure any of the terms exist somewhere in any of the fields. I think this is what we actually need, plus "relevance" (does that mean sphinx?) # conditions << term_conditions.collect{|c|"(#{c})"}.join(' AND ') #ANDing this will make it so that all the terms MUST appear in one field, eg author first and last name end conditions_sql = conditions.collect{|c|"(#{c})"}.join(' OR ') {:conditions => conditions_sql, :include => includes} end |
#quick_search_scopes ⇒ Object
for now, we’ll say that by definition, if a search_scope defines a lambda with one term, then it is a quick_search_scope
54 55 56 |
# File 'lib/search_scope.rb', line 54 def quick_search_scopes @quick_search_scopes ||= [] end |
#search(params = {}) ⇒ Object
this searches by chaining all of the named_scopes (search_scopes) that were included in the params
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/search_scope.rb', line 120 def search(params={}) paginate = params.delete :paginate aggregate_scope = self search_scopes(params).each do |scope| if scope.is_a? Symbol # aggregate_scope = aggregate_scope.send(scope) aggregate_scope = get_search_scope_from_object(aggregate_scope, scope) elsif scope.is_a? Array # aggregate_scope = aggregate_scope.send(*scope) aggregate_scope = get_search_scope_from_object(aggregate_scope, *scope) else raise "unsupported type for search scope: #{scope.inspect}" end end unless params[:quick_search].blank? aggregate_scope = aggregate_scope.scoped (params[:quick_search]) end if params[:sort_by] aggregate_scope = aggregate_scope.scoped (params[:sort_by]) end if paginate aggregate_scope.paginate(:all, :page => params[:page]) else aggregate_scope.find(:all) end end |
#search_scope(name, options = {}, &block) ⇒ Object
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/search_scope.rb', line 21 def search_scope(name, = {}, &block) puts "***search_scope: #{name.inspect} - #{.inspect}" #default the search to a LIKE search if nothing is given if .blank? = lambda { |term| { :conditions => ["#{table_name}.#{name} LIKE ?", "%#{term}%"] } } elsif .is_a?(Hash) && [:search_type] case [:search_type] when :exact_match = lambda { |term| { :conditions => ["#{table_name}.#{name} = ?", term] } } else raise "unknown search_type for search_scope: (#{name} - #{[:search_type]})" end end search_scope_keys << name unless search_scope_keys.include? name if .is_a? Proc quick_search_scopes << name if .arity == 1 end named_scope("search_#{name}".intern, , &block) end |
#search_scope_keys ⇒ Object
41 42 43 |
# File 'lib/search_scope.rb', line 41 def search_scope_keys @search_scope_keys ||= [] end |
#search_scopes(options = {}) ⇒ Object
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/search_scope.rb', line 68 def search_scopes(={}) scopes = [] search_scope_keys.each do |key| #if the scope key isn't in the params, don't include it next unless [key] # add the scope once for each term passed in (space delimited). this allows a search for 'star wars' to return only items where both terms match terms = [key].split.compact terms.each do |term| scopes << [key, term] end end # scopes << [:sort_search_scope, options[:sort_by]] if options[:sort_by] scopes end |
#sort_choices ⇒ Object
45 46 47 |
# File 'lib/search_scope.rb', line 45 def sort_choices @sort_choices ||= [] end |
#sort_choices_hash ⇒ Object
49 50 51 |
# File 'lib/search_scope.rb', line 49 def sort_choices_hash @sort_choices_hash ||= HashWithIndifferentAccess.new end |
#sort_search_by(name, options = {}) ⇒ Object
10 11 12 13 14 15 16 17 18 19 |
# File 'lib/search_scope.rb', line 10 def sort_search_by(name, ={}) [:label] ||= name.to_s.titleize [:order] ||= name.to_s raise "you must supply a Symbol for a name to new_sortable_by (#{name.inspect})" unless name.is_a? Symbol return if sort_choices_hash.keys.include? name.to_s #TODO put this back and get rid of the return above once I figure out how to reset the class vars when the class is reloaded # raise "there is already a sortable defined for the name (#{name.inspect}" if sort_choices_hash.keys.include? name.to_s sort_choices_hash[name] = SortScope.new(name, [:label], [:order], [:include]) sort_choices << sort_choices_hash[name] end |
#sort_search_by_options(sort_by) ⇒ Object
58 59 60 61 62 63 64 65 66 |
# File 'lib/search_scope.rb', line 58 def (sort_by) choices_hash = sort_choices_hash[sort_by] return {} unless choices_hash hash = { :order => choices_hash.order, :include => choices_hash.include_model, } hash end |