Class: Supernova::Criteria

Inherits:
Object
  • Object
show all
Defined in:
lib/supernova/criteria.rb

Direct Known Subclasses

SolrCriteria

Constant Summary collapse

DEFAULT_PER_PAGE =
25
FIRST_PAGE =
1

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(clazz = nil) ⇒ Criteria

Returns a new instance of Criteria.



34
35
36
37
38
39
# File 'lib/supernova/criteria.rb', line 34

def initialize(clazz = nil)
  self.clazz = clazz
  self.filters = {}
  self.search_options = {}
  self.immutable! if self.class.immutable_by_default?
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(*args, &block) ⇒ Object



259
260
261
262
263
264
265
266
267
268
# File 'lib/supernova/criteria.rb', line 259

def method_missing(*args, &block)
  if Supernova::Collection.instance_methods.map(&:to_s).include?(args.first.to_s)
    populate
    @results.send(*args, &block)
  elsif self.named_scope_defined?(args.first)
    self.merge(self.search_options[:named_scope_class].send(*args)) # merge named scope and current criteria
  else
    super
  end
end

Instance Attribute Details

#clazzObject

Returns the value of attribute clazz.



5
6
7
# File 'lib/supernova/criteria.rb', line 5

def clazz
  @clazz
end

#filtersObject

Returns the value of attribute filters.



5
6
7
# File 'lib/supernova/criteria.rb', line 5

def filters
  @filters
end

#resultsObject

Returns the value of attribute results.



5
6
7
# File 'lib/supernova/criteria.rb', line 5

def results
  @results
end

#search_optionsObject

Returns the value of attribute search_options.



5
6
7
# File 'lib/supernova/criteria.rb', line 5

def search_options
  @search_options
end

Class Method Details

.immutable_by_default!Object



21
22
23
# File 'lib/supernova/criteria.rb', line 21

def immutable_by_default!
  @immutable_by_default = true
end

.immutable_by_default?Boolean

Returns:

  • (Boolean)


29
30
31
# File 'lib/supernova/criteria.rb', line 29

def immutable_by_default?
  @immutable_by_default == true
end

.method_missing(*args) ⇒ Object



8
9
10
11
12
13
14
15
# File 'lib/supernova/criteria.rb', line 8

def method_missing(*args)
  scope = self.new
  if scope.respond_to?(args.first)
    scope.send(*args)
  else
    super
  end
end

.mutable_by_default!Object



25
26
27
# File 'lib/supernova/criteria.rb', line 25

def mutable_by_default!
  @immutable_by_default = false
end

.select(*args) ⇒ Object



17
18
19
# File 'lib/supernova/criteria.rb', line 17

def select(*args)
  self.new.send(:select, *args)
end

Instance Method Details

#attribute_mapping(mapping) ⇒ Object



53
54
55
# File 'lib/supernova/criteria.rb', line 53

def attribute_mapping(mapping)
  merge_search_options :attribute_mapping, mapping
end

#cloneObject



160
161
162
# File 'lib/supernova/criteria.rb', line 160

def clone
  Marshal.load(Marshal.dump(self))
end

#conditions(filters) ⇒ Object



103
104
105
# File 'lib/supernova/criteria.rb', line 103

def conditions(filters)
  merge_filters :conditions, filters
end

#current_pageObject



228
229
230
# File 'lib/supernova/criteria.rb', line 228

def current_page
  pagination_attribute_when_greater_zero(:page) || 1
end

#except(key) ⇒ Object



172
173
174
175
176
# File 'lib/supernova/criteria.rb', line 172

def except(key)
  self_or_clone.tap do |soc|
    soc.search_options.delete(key)
  end
end

#executeObject



224
225
226
# File 'lib/supernova/criteria.rb', line 224

def execute
  implement_in_subclass
end

#facet_fields(*fields) ⇒ Object



95
96
97
# File 'lib/supernova/criteria.rb', line 95

def facet_fields(*fields)
  merge_filters_array :facets, fields
end

#facet_queries(hash) ⇒ Object



99
100
101
# File 'lib/supernova/criteria.rb', line 99

def facet_queries(hash)
  merge_search_options :facet_queries, hash
end

#for_classes(clazzes) ⇒ Object



49
50
51
# File 'lib/supernova/criteria.rb', line 49

def for_classes(clazzes)
  merge_filters :classes, [clazzes].flatten
end

#group_by(group_option) ⇒ Object



65
66
67
# File 'lib/supernova/criteria.rb', line 65

def group_by(group_option)
  merge_search_options :group_by, group_option
end

#immutable!Object



41
42
43
# File 'lib/supernova/criteria.rb', line 41

def immutable!
  @immutable = true
end

#immutable?Boolean

Returns:

  • (Boolean)


45
46
47
# File 'lib/supernova/criteria.rb', line 45

def immutable?
  @immutable == true
end

#implement_in_subclassObject



244
245
246
# File 'lib/supernova/criteria.rb', line 244

def implement_in_subclass
  raise "implement in subclass"
end

#limit(limit_option) ⇒ Object



61
62
63
# File 'lib/supernova/criteria.rb', line 61

def limit(limit_option)
  merge_search_options :limit, limit_option
end

#merge(other_criteria) ⇒ Object



248
249
250
251
252
253
254
255
256
257
# File 'lib/supernova/criteria.rb', line 248

def merge(other_criteria)
  ret = self_or_clone
  other_criteria.filters.each do |key, value|
    ret = ret.merge_filters(key, value)
  end
  other_criteria.search_options.each do |key, value|
    ret = ret.merge_search_options(key, value)
  end
  ret
end

#merge_filters(key, value) ⇒ Object



147
148
149
# File 'lib/supernova/criteria.rb', line 147

def merge_filters(key, value)
  merge_filters_or_search_options(:filters, key, value)
end

#merge_filters_array(key, fields) ⇒ Object



151
152
153
154
155
156
157
158
# File 'lib/supernova/criteria.rb', line 151

def merge_filters_array(key, fields)
  self_or_clone.tap do |soc|
    soc.search_options[key] ||= Array.new
    fields.flatten.each do |field|
      soc.search_options[key] << field if !soc.search_options[key].include?(field)
    end
  end
end

#merge_filters_or_search_options(reference_method, key, value) ⇒ Object



182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/supernova/criteria.rb', line 182

def merge_filters_or_search_options(reference_method, key, value)
  self_or_clone.tap do |soc|
    reference = soc.send(reference_method)
    if key == :with
      reference[:with] ||= Array.new
      if valid_with_filter?(value)
        if value.is_a?(Array)
          reference[:with] += value
        else 
          reference[:with] << value
        end
      end
    elsif value.is_a?(Hash)
      reference[key] ||= Hash.new
      reference[key].merge!(value)
    elsif [:select, :order].include?(key)
      reference[key] ||= Array.new
      reference[key] += (value || [])
    else
      reference[key] = value
    end
  end
end

#merge_search_options(key, value) ⇒ Object



168
169
170
# File 'lib/supernova/criteria.rb', line 168

def merge_search_options(key, value)
  merge_filters_or_search_options(:search_options, key, value)
end

#named_scope_class(clazz) ⇒ Object



270
271
272
# File 'lib/supernova/criteria.rb', line 270

def named_scope_class(clazz)
  merge_search_options :named_scope_class, clazz
end

#named_scope_defined?(name) ⇒ Boolean

Returns:

  • (Boolean)


274
275
276
# File 'lib/supernova/criteria.rb', line 274

def named_scope_defined?(name)
  self.search_options[:named_scope_class] && self.search_options[:named_scope_class].respond_to?(:defined_named_search_scopes) && self.search_options[:named_scope_class].defined_named_search_scopes.respond_to?(:include?) && self.search_options[:named_scope_class].defined_named_search_scopes.include?(name)
end

#near(*coordinates) ⇒ Object



119
120
121
# File 'lib/supernova/criteria.rb', line 119

def near(*coordinates)
  merge_search_options :geo_center, normalize_coordinates(*coordinates)
end

#normalize_coordinates(*args) ⇒ Object



131
132
133
134
135
136
137
138
# File 'lib/supernova/criteria.rb', line 131

def normalize_coordinates(*args)
  flattened = args.flatten
  if (lat = read_first_attribute(flattened.first, :lat, :latitude)) && (lng = read_first_attribute(flattened.first, :lng, :lon, :longitude))
    { :lat => lat.to_f, :lng => lng.to_f }
  elsif flattened.length == 2
    { :lat => flattened.first.to_f, :lng => flattened.at(1).to_f }
  end
end

#options(options_hash) ⇒ Object



127
128
129
# File 'lib/supernova/criteria.rb', line 127

def options(options_hash)
  merge_search_options :custom_options, options_hash
end

#order(*order_options) ⇒ Object



57
58
59
# File 'lib/supernova/criteria.rb', line 57

def order(*order_options)
  merge_search_options :order, order_options
end

#paginate(pagination_options) ⇒ Object



107
108
109
# File 'lib/supernova/criteria.rb', line 107

def paginate(pagination_options)
  merge_search_options :pagination, pagination_options
end

#pagination_attribute_when_greater_zero(attribute) ⇒ Object



238
239
240
241
242
# File 'lib/supernova/criteria.rb', line 238

def pagination_attribute_when_greater_zero(attribute)
  if self.search_options[:pagination] && self.search_options[:pagination][attribute].to_i > 0
    self.search_options[:pagination][attribute] 
  end
end

#per_pageObject



232
233
234
235
236
# File 'lib/supernova/criteria.rb', line 232

def per_page
  ret = self.search_options[:pagination][:per_page] if self.search_options[:pagination]
  ret = DEFAULT_PER_PAGE if ret.nil?
  ret
end

#populateObject



210
211
212
213
# File 'lib/supernova/criteria.rb', line 210

def populate
  @results = execute if !populated?
  self
end

#populated?Boolean

Returns:

  • (Boolean)


220
221
222
# File 'lib/supernova/criteria.rb', line 220

def populated?
  instance_variables.map(&:to_s).include?("@results")
end

#read_first_attribute(object, *keys) ⇒ Object



140
141
142
143
144
145
# File 'lib/supernova/criteria.rb', line 140

def read_first_attribute(object, *keys)
  keys.each do |key|
    return object.send(key) if object.respond_to?(key)
  end
  nil
end

#rows(rows) ⇒ Object



111
112
113
# File 'lib/supernova/criteria.rb', line 111

def rows(rows)
  merge_search_options :rows, rows
end

#search(*terms) ⇒ Object



69
70
71
# File 'lib/supernova/criteria.rb', line 69

def search(*terms)
  merge_filters_array :search, terms
end

#select(*fields) ⇒ Object



91
92
93
# File 'lib/supernova/criteria.rb', line 91

def select(*fields)
  merge_filters_array :select, fields
end

#self_or_cloneObject



164
165
166
# File 'lib/supernova/criteria.rb', line 164

def self_or_clone
  immutable? ? clone : self
end

#start(start) ⇒ Object



115
116
117
# File 'lib/supernova/criteria.rb', line 115

def start(start)
  merge_search_options :start, start
end

#to_aObject



215
216
217
218
# File 'lib/supernova/criteria.rb', line 215

def to_a
  populate
  results
end

#to_parametersObject



206
207
208
# File 'lib/supernova/criteria.rb', line 206

def to_parameters
  implement_in_subclass
end

#valid_with_filter?(value) ⇒ Boolean

Returns:

  • (Boolean)


178
179
180
# File 'lib/supernova/criteria.rb', line 178

def valid_with_filter?(value)
  !(value.respond_to?(:blank?) && value.blank?) && !(value.respond_to?(:empty?) && value.empty?)
end

#where(*args) ⇒ Object



77
78
79
# File 'lib/supernova/criteria.rb', line 77

def where(*args)
  with(*args)
end

#with(filters) ⇒ Object



73
74
75
# File 'lib/supernova/criteria.rb', line 73

def with(filters)
  merge_search_options :with, filters
end

#within(distance) ⇒ Object



123
124
125
# File 'lib/supernova/criteria.rb', line 123

def within(distance)
  merge_search_options :geo_distance, distance
end

#without(filters) ⇒ Object



81
82
83
84
85
86
87
88
89
# File 'lib/supernova/criteria.rb', line 81

def without(filters)
  self_or_clone.tap do |soc|
    soc.filters[:without] ||= Hash.new
    filters.each do |key, value|
      soc.filters[:without][key] ||= Array.new
      soc.filters[:without][key] << value if !soc.filters[:without][key].include?(value)
    end
  end
end