Class: Supplejack::Search
- Inherits:
-
Object
- Object
- Supplejack::Search
- Includes:
- Request
- Defined in:
- lib/supplejack/search.rb
Overview
rubocop:disable Metrics/ClassLength FIXME: make me smaller!
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.
-
#geo_bbox ⇒ Object
Returns the value of attribute geo_bbox.
-
#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
#delete, #get, #patch, #post, #put
Constructor Details
#initialize(params = {}) ⇒ Search
Returns a new instance of Search.
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 53 54 55 56 57 58 |
# File 'lib/supplejack/search.rb', line 23 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
343 344 345 346 347 |
# File 'lib/supplejack/search.rb', line 343 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.
21 22 23 |
# File 'lib/supplejack/search.rb', line 21 def and @and end |
#api_params ⇒ Object
Returns the value of attribute api_params.
21 22 23 |
# File 'lib/supplejack/search.rb', line 21 def api_params @api_params end |
#direction ⇒ Object
Returns the value of attribute direction.
19 20 21 |
# File 'lib/supplejack/search.rb', line 19 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
69 70 71 |
# File 'lib/supplejack/search.rb', line 69 def filters @filters end |
#geo_bbox ⇒ Object
Returns the value of attribute geo_bbox.
20 21 22 |
# File 'lib/supplejack/search.rb', line 20 def geo_bbox @geo_bbox end |
#or ⇒ Object
Returns the value of attribute or.
21 22 23 |
# File 'lib/supplejack/search.rb', line 21 def or @or end |
#page ⇒ Object
Returns the value of attribute page.
19 20 21 |
# File 'lib/supplejack/search.rb', line 19 def page @page end |
#pagination_limit ⇒ Object
Returns the value of attribute pagination_limit.
19 20 21 |
# File 'lib/supplejack/search.rb', line 19 def pagination_limit @pagination_limit end |
#params ⇒ Object
Returns the value of attribute params.
21 22 23 |
# File 'lib/supplejack/search.rb', line 21 def params @params end |
#per_page ⇒ Object
Returns the value of attribute per_page.
19 20 21 |
# File 'lib/supplejack/search.rb', line 19 def per_page @per_page end |
#record_klass ⇒ Object
Returns the value of attribute record_klass.
20 21 22 |
# File 'lib/supplejack/search.rb', line 20 def record_klass @record_klass end |
#record_type ⇒ Object
Returns the value of attribute record_type.
20 21 22 |
# File 'lib/supplejack/search.rb', line 20 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.
128 129 130 |
# File 'lib/supplejack/search.rb', line 128 def results @results end |
#sort ⇒ Object
Returns the value of attribute sort.
20 21 22 |
# File 'lib/supplejack/search.rb', line 20 def sort @sort end |
#text ⇒ Object
Returns the value of attribute text.
19 20 21 |
# File 'lib/supplejack/search.rb', line 19 def text @text end |
#url_format ⇒ Object
Returns the value of attribute url_format.
21 22 23 |
# File 'lib/supplejack/search.rb', line 21 def url_format @url_format end |
#without ⇒ Object
Returns the value of attribute without.
21 22 23 |
# File 'lib/supplejack/search.rb', line 21 def without @without end |
Instance Method Details
#cacheable? ⇒ Boolean
315 316 317 318 |
# File 'lib/supplejack/search.rb', line 315 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
228 229 230 231 |
# File 'lib/supplejack/search.rb', line 228 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
rubocop:disable Metrics/LineLength rubocop:enable Metrics/LineLength
169 170 171 172 173 174 175 176 177 178 |
# File 'lib/supplejack/search.rb', line 169 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
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/supplejack/search.rb', line 200 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
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 |
# File 'lib/supplejack/search.rb', line 296 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
114 115 116 |
# File 'lib/supplejack/search.rb', line 114 def facet(value) self.facets.find { |facet| facet.name == value } end |
#facet_values(facet_name, options = {}) ⇒ Object
281 282 283 284 285 286 287 288 289 290 |
# File 'lib/supplejack/search.rb', line 281 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
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
# File 'lib/supplejack/search.rb', line 262 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
and responds to name and values
104 105 106 107 108 109 110 111 112 |
# File 'lib/supplejack/search.rb', line 104 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
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
# File 'lib/supplejack/search.rb', line 180 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
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 |
# File 'lib/supplejack/search.rb', line 237 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.
337 338 339 340 341 |
# File 'lib/supplejack/search.rb', line 337 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.
353 354 355 356 357 358 359 360 |
# File 'lib/supplejack/search.rb', line 353 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
89 90 91 |
# File 'lib/supplejack/search.rb', line 89 def (={}) @url_format.() end |
#record? ⇒ Boolean
154 155 156 |
# File 'lib/supplejack/search.rb', line 154 def record? self.record_type == 0 end |
#request_path ⇒ Object
292 293 294 |
# File 'lib/supplejack/search.rb', line 292 def request_path '/records' end |
#total ⇒ Object
Returns the total amount of records for the current search filters
148 149 150 151 152 |
# File 'lib/supplejack/search.rb', line 148 def total return @total if @total self.execute_request @total = @response['search']['result_count'].to_i end |