Class: Supplejack::Search
- Inherits:
-
Object
- Object
- Supplejack::Search
- Includes:
- Request
- Defined in:
- lib/supplejack/search.rb
Instance Attribute Summary collapse
-
#and ⇒ Object
Returns the value of attribute and.
-
#api_params ⇒ Object
Returns the value of attribute api_params.
-
#direction ⇒ Object
Returns the value of attribute direction.
-
#filters(options = {}) ⇒ Array<Array>
Returns by default a array of two element arrays with all the active filters in the search object and their values.
-
#or ⇒ Object
Returns the value of attribute or.
-
#page ⇒ Object
Returns the value of attribute page.
-
#pagination_limit ⇒ Object
Returns the value of attribute pagination_limit.
-
#params ⇒ Object
Returns the value of attribute params.
-
#per_page ⇒ Object
Returns the value of attribute per_page.
-
#record_klass ⇒ Object
Returns the value of attribute record_klass.
-
#record_type ⇒ Object
Returns the value of attribute record_type.
-
#results ⇒ Array
Returns a array of
Supplejack::Record
objects wrapped in a Paginated Collection which provides methods for will_paginate and kaminari to work properly. -
#sort ⇒ Object
Returns the value of attribute sort.
-
#text ⇒ Object
Returns the value of attribute text.
-
#url_format ⇒ Object
Returns the value of attribute url_format.
-
#without ⇒ Object
Returns the value of attribute without.
Instance Method Summary collapse
- #cacheable? ⇒ Boolean
-
#categories(options = {}) ⇒ Hash{String => Integer}
Gets the category facet unrestricted by the current category filter.
-
#counts(query_parameters = {}) ⇒ Hash{String => Integer}
Calculates counts for specific queries using solr’s facet.query.
-
#counts_params(query_parameters = {}) ⇒ Object
Returns a hash with all the parameters required by the counts method.
- #execute_request ⇒ Object
- #facet(value) ⇒ Object
- #facet_values(facet_name, options = {}) ⇒ Object
-
#facet_values_params(facet_name, options = {}) ⇒ Object
Returns a hash with all the parameters required by the facet_values method.
-
#facets(options = {}) ⇒ Array<Supplejack::Facet>
Returns an array of facets for the current search criteria sorted by the order specified in
Supplejack.facets
. - #fetch_counts(query_parameters = {}) ⇒ Object
-
#fetch_facet_values(facet_name, options = {}) ⇒ Hash{String => Integer}
Gets the facet values unrestricted by the current filter.
-
#has_filter_and_value?(filter, value) ⇒ Boolean
Convienence method to find out if the search object has any specific filter applied to it.
-
#initialize(params = {}) ⇒ Search
constructor
A new instance of Search.
-
#merge_extra_filters(existing_filters) ⇒ Object
Adds any filters defined in the :or, :and or :without attr_accessors By setting them directly it allows to nest any conditions that is not normally possible though the item_hash URL format.
- #method_missing(symbol, *args, &block) ⇒ Object
- #options(filter_options = {}) ⇒ Object
- #record? ⇒ Boolean
- #request_path ⇒ Object
-
#total ⇒ Object
Returns the total amount of records for the current search filters.
Methods included from Request
Constructor Details
#initialize(params = {}) ⇒ Search
Returns a new instance of Search.
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/supplejack/search.rb', line 18 def initialize(params={}) @params = params.clone rescue {} @params[:facets] ||= Supplejack.facets.join(',') @params[:facets_per_page] ||= Supplejack.facets_per_page [:action, :controller].each {|p| @params.delete(p) } @text = @params[:text] @geo_bbox = @params[:geo_bbox] @record_type = @params[:record_type] @record_type = @record_type.to_i unless @record_type == "all" @page = (@params[:page] || 1).to_i @per_page = (@params[:per_page] || Supplejack.per_page).to_i @pagination_limit = @params[:pagination_limit] || Supplejack.pagination_limit @sort = @params[:sort] @direction = @params[:direction] @url_format = Supplejack.url_format_klass.new(@params, self) @filters = @url_format.filters @api_params = @url_format.to_api_hash @record_klass = @params[:record_klass] || Supplejack.record_klass # Do not execute the actual search right away, it should be lazy loaded # when the user needs one of the following values. @total = nil @results = nil @facets = nil Supplejack.search_attributes.each do |attribute| # We have to define the attribute accessors for the filters at initialization of the search instance # otherwise because the rails initializer is run after the gem was loaded, only the default # Supplejack.search_attributes set in the Gem would be defined. self.class.send(:attr_accessor, attribute) self.send("#{attribute}=", @filters[attribute]) unless @filters[attribute] == 'all' end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(symbol, *args, &block) ⇒ Object
335 336 337 338 339 |
# File 'lib/supplejack/search.rb', line 335 def method_missing(symbol, *args, &block) if symbol.to_s.match(/has_(.+)\?/) && Supplejack.search_attributes.include?($1.to_sym) return has_filter_and_value?($1, args.first) end end |
Instance Attribute Details
#and ⇒ Object
Returns the value of attribute and.
16 17 18 |
# File 'lib/supplejack/search.rb', line 16 def and @and end |
#api_params ⇒ Object
Returns the value of attribute api_params.
16 17 18 |
# File 'lib/supplejack/search.rb', line 16 def api_params @api_params end |
#direction ⇒ Object
Returns the value of attribute direction.
15 16 17 |
# File 'lib/supplejack/search.rb', line 15 def direction @direction end |
#filters(options = {}) ⇒ Array<Array>
Returns by default a array of two element arrays with all the active filters in the search object and their values
63 64 65 |
# File 'lib/supplejack/search.rb', line 63 def filters @filters end |
#or ⇒ Object
Returns the value of attribute or.
16 17 18 |
# File 'lib/supplejack/search.rb', line 16 def or @or end |
#page ⇒ Object
Returns the value of attribute page.
15 16 17 |
# File 'lib/supplejack/search.rb', line 15 def page @page end |
#pagination_limit ⇒ Object
Returns the value of attribute pagination_limit.
15 16 17 |
# File 'lib/supplejack/search.rb', line 15 def pagination_limit @pagination_limit end |
#params ⇒ Object
Returns the value of attribute params.
16 17 18 |
# File 'lib/supplejack/search.rb', line 16 def params @params end |
#per_page ⇒ Object
Returns the value of attribute per_page.
15 16 17 |
# File 'lib/supplejack/search.rb', line 15 def per_page @per_page end |
#record_klass ⇒ Object
Returns the value of attribute record_klass.
15 16 17 |
# File 'lib/supplejack/search.rb', line 15 def record_klass @record_klass end |
#record_type ⇒ Object
Returns the value of attribute record_type.
15 16 17 |
# File 'lib/supplejack/search.rb', line 15 def record_type @record_type end |
#results ⇒ Array
Returns a array of Supplejack::Record
objects wrapped in a Paginated Collection which provides methods for will_paginate and kaminari to work properly
It will initialize the Supplejack::Record
objects with the class stored in Supplejack.record_klass
, so that you can override any method provided by the Supplejack::Record
module or create new methods. You can also provide a :record_klass
option when initialing a Supplejack::Search
object to override the record_klass on a per request basis.
121 122 123 |
# File 'lib/supplejack/search.rb', line 121 def results @results end |
#sort ⇒ Object
Returns the value of attribute sort.
15 16 17 |
# File 'lib/supplejack/search.rb', line 15 def sort @sort end |
#text ⇒ Object
Returns the value of attribute text.
15 16 17 |
# File 'lib/supplejack/search.rb', line 15 def text @text end |
#url_format ⇒ Object
Returns the value of attribute url_format.
16 17 18 |
# File 'lib/supplejack/search.rb', line 16 def url_format @url_format end |
#without ⇒ Object
Returns the value of attribute without.
16 17 18 |
# File 'lib/supplejack/search.rb', line 16 def without @without end |
Instance Method Details
#cacheable? ⇒ Boolean
307 308 309 310 |
# File 'lib/supplejack/search.rb', line 307 def cacheable? return false if text.present? || page > 1 return true end |
#categories(options = {}) ⇒ Hash{String => Integer}
Gets the category facet unrestricted by the current category filter
220 221 222 223 |
# File 'lib/supplejack/search.rb', line 220 def categories(={}) return @categories if @categories @categories = facet_values('category', ) end |
#counts(query_parameters = {}) ⇒ Hash{String => Integer}
Calculates counts for specific queries using solr’s facet.query
161 162 163 164 165 166 167 168 169 170 |
# File 'lib/supplejack/search.rb', line 161 def counts(query_parameters={}) if Supplejack.enable_caching cache_key = Digest::MD5.hexdigest(counts_params(query_parameters).to_query) Rails.cache.fetch(cache_key, :expires_in => 1.day) do fetch_counts(query_parameters) end else fetch_counts(query_parameters) end end |
#counts_params(query_parameters = {}) ⇒ Object
Returns a hash with all the parameters required by the counts method
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 |
# File 'lib/supplejack/search.rb', line 192 def counts_params(query_parameters={}) query_with_filters = {} query_parameters.each_pair do |count_name, count_filters| count_filters = count_filters.symbolize_keys query_record_type = count_filters[:record_type].to_i type = query_record_type == 0 ? :items : :headings filters = self.url_format.and_filters(type).dup without_filters = self.url_format.without_filters(type).dup without_filters = Hash[without_filters.map {|key, value| ["-#{key}".to_sym, value]}] filters.merge!(without_filters) query_with_filters.merge!({count_name.to_sym => Supplejack::Util.deep_merge(filters, count_filters) }) end params = {:facet_query => query_with_filters, :record_type => "all"} params[:text] = self.url_format.text params[:text] = self.text if self.text.present? # params[:geo_bbox] = self.geo_bbox if self.geo_bbox.present? params[:query_fields] = self.url_format.query_fields params = merge_extra_filters(params) params end |
#execute_request ⇒ Object
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 |
# File 'lib/supplejack/search.rb', line 288 def execute_request return @response if @response @api_params = merge_extra_filters(@api_params) begin if Supplejack.enable_caching && self.cacheable? cache_key = Digest::MD5.hexdigest("#{request_path}?#{@api_params.to_query}") @response = Rails.cache.fetch(cache_key, expires_in: 1.hour) do get(request_path, @api_params) end else @response = get(request_path, @api_params) end rescue StandardError => e @response = {'search' => {}} end end |
#facet(value) ⇒ Object
107 108 109 |
# File 'lib/supplejack/search.rb', line 107 def facet(value) self.facets.find { |facet| facet.name == value } end |
#facet_values(facet_name, options = {}) ⇒ Object
273 274 275 276 277 278 279 280 281 282 |
# File 'lib/supplejack/search.rb', line 273 def facet_values(facet_name, ={}) if Supplejack.enable_caching cache_key = Digest::MD5.hexdigest(facet_values_params(facet_name).to_query) Rails.cache.fetch(cache_key, :expires_in => 1.day) do fetch_facet_values(facet_name, ) end else fetch_facet_values(facet_name, ) end end |
#facet_values_params(facet_name, options = {}) ⇒ Object
Returns a hash with all the parameters required by the facet_values method
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 |
# File 'lib/supplejack/search.rb', line 254 def facet_values_params(facet_name, ={}) memoized_values = instance_variable_get("@#{facet_name}_params") return memoized_values if memoized_values filters = self.url_format.and_filters filters.delete(facet_name.to_sym) facet_params = self.api_params facet_params[:and] = filters facet_params[:facets] = "#{facet_name}" facet_params[:per_page] = 0 facet_params[:facets_per_page] = [:facets_per_page] if [:facets_per_page] facet_params = merge_extra_filters(facet_params) instance_variable_set("@#{facet_name}_params", facet_params) facet_params end |
#facets(options = {}) ⇒ Array<Supplejack::Facet>
Returns an array of facets for the current search criteria sorted by the order specified in Supplejack.facets
97 98 99 100 101 102 103 104 105 |
# File 'lib/supplejack/search.rb', line 97 def facets(={}) return @facets if @facets self.execute_request facets = @response['search']['facets'] || {} facet_array = facets.sort_by {|facet, rows| Supplejack.facets.find_index(facet.to_sym) || 100 } @facets = facet_array.map {|name, values| Supplejack::Facet.new(name, values) } end |
#fetch_counts(query_parameters = {}) ⇒ Object
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
# File 'lib/supplejack/search.rb', line 172 def fetch_counts(query_parameters={}) begin response = get(request_path, counts_params(query_parameters)) counts_hash = response['search']['facets']['counts'] rescue StandardError => e counts_hash = {} end # When the search doesn't match any facets for the specified filters, Sunspot doesn't return any facets # at all. Here we add those keys with a value of 0. # query_parameters.each_pair do |count_name, count_filters| counts_hash[count_name.to_s] = 0 unless counts_hash[count_name.to_s] end counts_hash end |
#fetch_facet_values(facet_name, options = {}) ⇒ Hash{String => Integer}
Gets the facet values unrestricted by the current filter
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 |
# File 'lib/supplejack/search.rb', line 229 def fetch_facet_values(facet_name, ={}) .reverse_merge!(:all => true, :sort => nil) memoized_values = instance_variable_get("@#{facet_name}_values") return memoized_values if memoized_values begin response = get(request_path, facet_values_params(facet_name, )) @facet_values = response["search"]["facets"]["#{facet_name}"] rescue StandardError => e response = {"search" => {"result_count" => 0}} @facet_values = {} end @facet_values["All"] = response["search"]["result_count"] if [:all] facet = Supplejack::Facet.new(facet_name, @facet_values) @facet_values = facet.values([:sort]) instance_variable_set("@#{facet_name}_values", @facet_values) @facet_values end |
#has_filter_and_value?(filter, value) ⇒ Boolean
Convienence method to find out if the search object has any specific filter applied to it. It works for both single and multiple value filters. This methods are actually defined on method_missing.
329 330 331 332 333 |
# File 'lib/supplejack/search.rb', line 329 def has_filter_and_value?(filter, value) actual_value = *self.send(filter) return false unless actual_value actual_value.include?(value) end |
#merge_extra_filters(existing_filters) ⇒ Object
Adds any filters defined in the :or, :and or :without attr_accessors By setting them directly it allows to nest any conditions that is not normally possible though the item_hash URL format.
345 346 347 348 349 350 351 352 |
# File 'lib/supplejack/search.rb', line 345 def merge_extra_filters(existing_filters) and_filters = self.and.try(:any?) ? {:and => self.and} : {} or_filters = self.or.try(:any?) ? {:or => self.or} : {} without_filters = self.without.try(:any?) ? {:without => self.without} : {} extra_filters = and_filters.merge(or_filters).merge(without_filters) Util.deep_merge(existing_filters, extra_filters) end |
#options(filter_options = {}) ⇒ Object
83 84 85 |
# File 'lib/supplejack/search.rb', line 83 def (={}) @url_format.() end |
#record? ⇒ Boolean
147 148 149 |
# File 'lib/supplejack/search.rb', line 147 def record? self.record_type == 0 end |
#request_path ⇒ Object
284 285 286 |
# File 'lib/supplejack/search.rb', line 284 def request_path '/records' end |
#total ⇒ Object
Returns the total amount of records for the current search filters
141 142 143 144 145 |
# File 'lib/supplejack/search.rb', line 141 def total return @total if @total self.execute_request @total = @response['search']['result_count'].to_i end |