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
Constructor Details
#initialize(params = {}) ⇒ Search
Returns a new instance of Search.
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 53 54 55 56 |
# File 'lib/supplejack/search.rb', line 21 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
341 342 343 344 345 |
# File 'lib/supplejack/search.rb', line 341 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.
19 20 21 |
# File 'lib/supplejack/search.rb', line 19 def and @and end |
#api_params ⇒ Object
Returns the value of attribute api_params.
19 20 21 |
# File 'lib/supplejack/search.rb', line 19 def api_params @api_params end |
#direction ⇒ Object
Returns the value of attribute direction.
17 18 19 |
# File 'lib/supplejack/search.rb', line 17 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
67 68 69 |
# File 'lib/supplejack/search.rb', line 67 def filters @filters end |
#geo_bbox ⇒ Object
Returns the value of attribute geo_bbox.
18 19 20 |
# File 'lib/supplejack/search.rb', line 18 def geo_bbox @geo_bbox end |
#or ⇒ Object
Returns the value of attribute or.
19 20 21 |
# File 'lib/supplejack/search.rb', line 19 def or @or end |
#page ⇒ Object
Returns the value of attribute page.
17 18 19 |
# File 'lib/supplejack/search.rb', line 17 def page @page end |
#pagination_limit ⇒ Object
Returns the value of attribute pagination_limit.
17 18 19 |
# File 'lib/supplejack/search.rb', line 17 def pagination_limit @pagination_limit end |
#params ⇒ Object
Returns the value of attribute params.
19 20 21 |
# File 'lib/supplejack/search.rb', line 19 def params @params end |
#per_page ⇒ Object
Returns the value of attribute per_page.
17 18 19 |
# File 'lib/supplejack/search.rb', line 17 def per_page @per_page end |
#record_klass ⇒ Object
Returns the value of attribute record_klass.
18 19 20 |
# File 'lib/supplejack/search.rb', line 18 def record_klass @record_klass end |
#record_type ⇒ Object
Returns the value of attribute record_type.
18 19 20 |
# File 'lib/supplejack/search.rb', line 18 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.
126 127 128 |
# File 'lib/supplejack/search.rb', line 126 def results @results end |
#sort ⇒ Object
Returns the value of attribute sort.
18 19 20 |
# File 'lib/supplejack/search.rb', line 18 def sort @sort end |
#text ⇒ Object
Returns the value of attribute text.
17 18 19 |
# File 'lib/supplejack/search.rb', line 17 def text @text end |
#url_format ⇒ Object
Returns the value of attribute url_format.
19 20 21 |
# File 'lib/supplejack/search.rb', line 19 def url_format @url_format end |
#without ⇒ Object
Returns the value of attribute without.
19 20 21 |
# File 'lib/supplejack/search.rb', line 19 def without @without end |
Instance Method Details
#cacheable? ⇒ Boolean
313 314 315 316 |
# File 'lib/supplejack/search.rb', line 313 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
226 227 228 229 |
# File 'lib/supplejack/search.rb', line 226 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
167 168 169 170 171 172 173 174 175 176 |
# File 'lib/supplejack/search.rb', line 167 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
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 |
# File 'lib/supplejack/search.rb', line 198 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
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 |
# File 'lib/supplejack/search.rb', line 294 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
112 113 114 |
# File 'lib/supplejack/search.rb', line 112 def facet(value) self.facets.find { |facet| facet.name == value } end |
#facet_values(facet_name, options = {}) ⇒ Object
279 280 281 282 283 284 285 286 287 288 |
# File 'lib/supplejack/search.rb', line 279 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
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 |
# File 'lib/supplejack/search.rb', line 260 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
102 103 104 105 106 107 108 109 110 |
# File 'lib/supplejack/search.rb', line 102 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
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/supplejack/search.rb', line 178 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
235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 |
# File 'lib/supplejack/search.rb', line 235 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.
335 336 337 338 339 |
# File 'lib/supplejack/search.rb', line 335 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.
351 352 353 354 355 356 357 358 |
# File 'lib/supplejack/search.rb', line 351 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
87 88 89 |
# File 'lib/supplejack/search.rb', line 87 def (={}) @url_format.() end |
#record? ⇒ Boolean
152 153 154 |
# File 'lib/supplejack/search.rb', line 152 def record? self.record_type == 0 end |
#request_path ⇒ Object
290 291 292 |
# File 'lib/supplejack/search.rb', line 290 def request_path '/records' end |
#total ⇒ Object
Returns the total amount of records for the current search filters
146 147 148 149 150 |
# File 'lib/supplejack/search.rb', line 146 def total return @total if @total self.execute_request @total = @response['search']['result_count'].to_i end |