searchgasm 1.2.2 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.rdoc +8 -0
- data/Manifest +42 -3
- data/README.rdoc +101 -82
- data/TODO.rdoc +1 -3
- data/lib/searchgasm/active_record/connection_adapters/mysql_adapter.rb +143 -6
- data/lib/searchgasm/active_record/connection_adapters/postgresql_adapter.rb +148 -0
- data/lib/searchgasm/active_record/connection_adapters/sqlite_adapter.rb +54 -0
- data/lib/searchgasm/condition/base.rb +59 -86
- data/lib/searchgasm/condition/begins_with.rb +3 -8
- data/lib/searchgasm/condition/blank.rb +5 -5
- data/lib/searchgasm/condition/ends_with.rb +3 -8
- data/lib/searchgasm/condition/equals.rb +4 -3
- data/lib/searchgasm/condition/greater_than.rb +3 -14
- data/lib/searchgasm/condition/greater_than_or_equal_to.rb +3 -14
- data/lib/searchgasm/condition/keywords.rb +3 -8
- data/lib/searchgasm/condition/less_than.rb +3 -14
- data/lib/searchgasm/condition/less_than_or_equal_to.rb +3 -14
- data/lib/searchgasm/condition/like.rb +15 -0
- data/lib/searchgasm/condition/nil.rb +5 -5
- data/lib/searchgasm/condition/not_begin_with.rb +17 -0
- data/lib/searchgasm/condition/not_end_with.rb +17 -0
- data/lib/searchgasm/condition/{does_not_equal.rb → not_equal.rb} +5 -4
- data/lib/searchgasm/condition/not_have_keywords.rb +17 -0
- data/lib/searchgasm/condition/not_like.rb +17 -0
- data/lib/searchgasm/condition/tree.rb +4 -5
- data/lib/searchgasm/conditions/base.rb +218 -72
- data/lib/searchgasm/modifiers/absolute.rb +15 -0
- data/lib/searchgasm/modifiers/acos.rb +11 -0
- data/lib/searchgasm/modifiers/asin.rb +11 -0
- data/lib/searchgasm/modifiers/atan.rb +11 -0
- data/lib/searchgasm/modifiers/base.rb +27 -0
- data/lib/searchgasm/modifiers/ceil.rb +15 -0
- data/lib/searchgasm/modifiers/char_length.rb +15 -0
- data/lib/searchgasm/modifiers/cos.rb +15 -0
- data/lib/searchgasm/modifiers/cot.rb +15 -0
- data/lib/searchgasm/modifiers/day_of_month.rb +15 -0
- data/lib/searchgasm/modifiers/day_of_week.rb +15 -0
- data/lib/searchgasm/modifiers/day_of_year.rb +15 -0
- data/lib/searchgasm/modifiers/degrees.rb +11 -0
- data/lib/searchgasm/modifiers/exp.rb +15 -0
- data/lib/searchgasm/modifiers/floor.rb +15 -0
- data/lib/searchgasm/modifiers/hex.rb +11 -0
- data/lib/searchgasm/modifiers/hour.rb +11 -0
- data/lib/searchgasm/modifiers/log.rb +15 -0
- data/lib/searchgasm/modifiers/log10.rb +11 -0
- data/lib/searchgasm/modifiers/log2.rb +11 -0
- data/lib/searchgasm/modifiers/md5.rb +11 -0
- data/lib/searchgasm/modifiers/microseconds.rb +11 -0
- data/lib/searchgasm/modifiers/milliseconds.rb +11 -0
- data/lib/searchgasm/modifiers/minute.rb +15 -0
- data/lib/searchgasm/modifiers/month.rb +15 -0
- data/lib/searchgasm/modifiers/octal.rb +15 -0
- data/lib/searchgasm/modifiers/radians.rb +11 -0
- data/lib/searchgasm/modifiers/round.rb +11 -0
- data/lib/searchgasm/modifiers/second.rb +15 -0
- data/lib/searchgasm/modifiers/sign.rb +11 -0
- data/lib/searchgasm/modifiers/sin.rb +11 -0
- data/lib/searchgasm/modifiers/square_root.rb +15 -0
- data/lib/searchgasm/modifiers/tan.rb +15 -0
- data/lib/searchgasm/modifiers/week.rb +11 -0
- data/lib/searchgasm/modifiers/year.rb +11 -0
- data/lib/searchgasm/shared/utilities.rb +0 -10
- data/lib/searchgasm/version.rb +2 -2
- data/lib/searchgasm.rb +15 -19
- data/searchgasm.gemspec +86 -9
- data/test/libs/ordered_hash.rb +9 -0
- data/test/test_condition_base.rb +21 -47
- data/test/test_condition_types.rb +44 -44
- data/test/test_conditions_base.rb +34 -21
- data/test/test_helper.rb +1 -0
- data/test/test_search_conditions.rb +1 -1
- metadata +85 -8
- data/lib/searchgasm/condition/contains.rb +0 -20
- data/lib/searchgasm/condition/during_evening.rb +0 -32
@@ -13,36 +13,51 @@ module Searchgasm
|
|
13
13
|
class << self
|
14
14
|
attr_accessor :added_klass_conditions, :added_column_conditions, :added_associations
|
15
15
|
|
16
|
-
|
16
|
+
def column_details # :nodoc:
|
17
|
+
return @column_details if @column_details
|
18
|
+
|
19
|
+
@column_details = []
|
20
|
+
|
21
|
+
klass.columns.each do |column|
|
22
|
+
column_detail = {:column => column}
|
23
|
+
column_detail[:aliases] = case column.type
|
24
|
+
when :datetime, :time, :timestamp
|
25
|
+
[column.name.gsub(/_at$/, "")]
|
26
|
+
when :date
|
27
|
+
[column.name.gsub(/_at$/, "")]
|
28
|
+
else
|
29
|
+
[]
|
30
|
+
end
|
31
|
+
|
32
|
+
@column_details << column_detail
|
33
|
+
end
|
34
|
+
|
35
|
+
@column_details
|
36
|
+
end
|
37
|
+
|
38
|
+
# Registers a condition as an available condition for a column or a class. MySQL supports a "sounds like" function. I want to use it, so let's add it.
|
17
39
|
#
|
18
40
|
# === Example
|
19
41
|
#
|
20
|
-
# config/initializers/searchgasm.rb
|
42
|
+
# # config/initializers/searchgasm.rb
|
21
43
|
# # Actual function for MySQL databases only
|
22
44
|
# class SoundsLike < Searchgasm::Condition::Base
|
23
|
-
# class
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
# def name_for_column(column)
|
28
|
-
# super
|
29
|
-
# end
|
30
|
-
#
|
31
|
-
# # Only do this if you want aliases for your condition
|
32
|
-
# def aliases_for_column(column)
|
33
|
-
# ["#{column.name}_sounds", "#{column.name}_similar_to"]
|
34
|
-
# end
|
45
|
+
# # The name of the conditions. By default its the name of the class, if you want alternate or alias conditions just add them on.
|
46
|
+
# # If you don't want to add aliases you don't even need to define this method
|
47
|
+
# def self.name_for_column(column)
|
48
|
+
# super
|
35
49
|
# end
|
36
50
|
#
|
37
51
|
# # You can return an array or a string. NOT a hash, because all of these conditions
|
38
52
|
# # need to eventually get merged together. The array or string can be anything you would put in
|
39
|
-
# # the :conditions option for ActiveRecord::Base.find(). Also
|
53
|
+
# # the :conditions option for ActiveRecord::Base.find(). Also notice the column_sql variable. This is essentail
|
54
|
+
# # for applying modifiers and should be used in your conditions wherever you want the column.
|
40
55
|
# def to_conditions(value)
|
41
|
-
# ["#{
|
56
|
+
# ["#{column_sql} SOUNDS LIKE ?", value]
|
42
57
|
# end
|
43
58
|
# end
|
44
59
|
#
|
45
|
-
# Searchgasm::Seearch::Conditions.register_condition(
|
60
|
+
# Searchgasm::Seearch::Conditions.register_condition(SoundsLike)
|
46
61
|
def register_condition(condition_class)
|
47
62
|
raise(ArgumentError, "You can only register conditions that extend Searchgasm::Condition::Base") unless condition_class.ancestors.include?(Searchgasm::Condition::Base)
|
48
63
|
conditions << condition_class unless conditions.include?(condition_class)
|
@@ -53,6 +68,57 @@ module Searchgasm
|
|
53
68
|
@@conditions ||= []
|
54
69
|
end
|
55
70
|
|
71
|
+
# Registers a modifier as an available modifier for each column.
|
72
|
+
#
|
73
|
+
# === Example
|
74
|
+
#
|
75
|
+
# # config/initializers/searchgasm.rb
|
76
|
+
# class Ceil < Searchgasm::Modifiers::Base
|
77
|
+
# # The name of the modifier. By default its the name of the class, if you want alternate or alias modifiers just add them on.
|
78
|
+
# # If you don't want to add aliases you don't even need to define this method
|
79
|
+
# def self.modifier_names
|
80
|
+
# super + ["round_up"]
|
81
|
+
# end
|
82
|
+
#
|
83
|
+
# # The name of the method in the connection adapters (see below). By default its the name of your class suffixed with "_sql".
|
84
|
+
# # So in this example it would be "ceil_sql". Unless you want to change that you don't need to define this method.
|
85
|
+
# def self.adapter_method_name
|
86
|
+
# super
|
87
|
+
# end
|
88
|
+
#
|
89
|
+
# # This is the type of value returned from the modifier. This is neccessary for typcasting values for the modifier when
|
90
|
+
# # applied to a column
|
91
|
+
# def self.return_type
|
92
|
+
# :integer
|
93
|
+
# end
|
94
|
+
# end
|
95
|
+
#
|
96
|
+
# Searchgasm::Seearch::Conditions.register_modifiers(Ceil)
|
97
|
+
#
|
98
|
+
# Now here's the fun part, applying this modifier to each connection adapter. Some databases call modifiers differently. If they all apply them the same you can
|
99
|
+
# add in the function to ActiveRecord::ConnectionAdapters::AbstractAdapter, otherwise you need to add them to each
|
100
|
+
# individually: ActiveRecord::ConnectionAdapters::MysqlAdapter, ActiveRecord::ConnectionAdapters::PostgreSQLAdapter, ActiveRecord::ConnectionAdapters::SQLiteAdapter
|
101
|
+
#
|
102
|
+
# Do this by includine a model with your method. The name of your method, by default, is: #{modifier_name}_sql. So in the example above it would be "ceil_sql"
|
103
|
+
#
|
104
|
+
# module CeilAdapterMethod
|
105
|
+
# def ceil_sql(column_name)
|
106
|
+
# "CEIL(#{column_name})"
|
107
|
+
# end
|
108
|
+
# end
|
109
|
+
#
|
110
|
+
# ActiveRecord::ConnectionAdapters::MysqlAdapter.send(:include, CeilAdapterMethod)
|
111
|
+
# # ... include for the rest of the adapters
|
112
|
+
def register_modifier(modifier_class)
|
113
|
+
raise(ArgumentError, "You can only register conditions that extend Searchgasm::Modifiers::Base") unless modifier_class.ancestors.include?(Searchgasm::Modifiers::Base)
|
114
|
+
modifiers << modifier_class unless modifiers.include?(modifier_class)
|
115
|
+
end
|
116
|
+
|
117
|
+
# A list of available modifier classes
|
118
|
+
def modifiers
|
119
|
+
@@modifiers ||= []
|
120
|
+
end
|
121
|
+
|
56
122
|
# A list of all associations created, used for caching and performance
|
57
123
|
def association_names
|
58
124
|
@association_names ||= []
|
@@ -82,8 +148,6 @@ module Searchgasm
|
|
82
148
|
end
|
83
149
|
|
84
150
|
def initialize(init_conditions = {})
|
85
|
-
add_klass_conditions!
|
86
|
-
add_column_conditions!
|
87
151
|
add_associations!
|
88
152
|
self.conditions = init_conditions
|
89
153
|
end
|
@@ -95,7 +159,7 @@ module Searchgasm
|
|
95
159
|
# search.conditions.any = true # will join all conditions with "or", you can also set this to "true", "1", or "yes"
|
96
160
|
# search.conditions.any = false # will join all conditions with "and"
|
97
161
|
def any=(value)
|
98
|
-
associations.each { |association| association.any = value }
|
162
|
+
associations.each { |name, association| association.any = value }
|
99
163
|
@any = value
|
100
164
|
end
|
101
165
|
|
@@ -111,7 +175,7 @@ module Searchgasm
|
|
111
175
|
# A list of joins to use when searching, includes relationships
|
112
176
|
def auto_joins
|
113
177
|
j = []
|
114
|
-
associations.each do |association|
|
178
|
+
associations.each do |name, association|
|
115
179
|
next if association.conditions.blank?
|
116
180
|
association_joins = association.auto_joins
|
117
181
|
j << (association_joins.blank? ? association.relationship_name.to_sym : {association.relationship_name.to_sym => association_joins})
|
@@ -126,16 +190,15 @@ module Searchgasm
|
|
126
190
|
# Sanitizes the conditions down into conditions that ActiveRecord::Base.find can understand.
|
127
191
|
def sanitize
|
128
192
|
return @conditions if @conditions
|
129
|
-
merge_conditions(*(objects.collect { |object| object.sanitize } << {:any => any}))
|
193
|
+
merge_conditions(*(objects.collect { |name, object| object.sanitize } << {:any => any}))
|
130
194
|
end
|
131
195
|
|
132
196
|
# Allows you to set the conditions via a hash.
|
133
197
|
def conditions=(value)
|
134
198
|
case value
|
135
|
-
when Hash
|
199
|
+
when Hash
|
136
200
|
assert_valid_conditions(value)
|
137
201
|
remove_conditions_from_protected_assignement(value).each do |condition, condition_value|
|
138
|
-
next if meaningless?(condition_value) # ignore blanks on mass assignments
|
139
202
|
send("#{condition}=", condition_value)
|
140
203
|
end
|
141
204
|
else
|
@@ -150,14 +213,14 @@ module Searchgasm
|
|
150
213
|
return if objects.blank?
|
151
214
|
|
152
215
|
conditions_hash = {}
|
153
|
-
objects.each do |object|
|
216
|
+
objects.each do |name, object|
|
154
217
|
if object.class < Searchgasm::Conditions::Base
|
155
218
|
relationship_conditions = object.conditions
|
156
219
|
next if relationship_conditions.blank?
|
157
220
|
conditions_hash[object.relationship_name.to_sym] = relationship_conditions
|
158
221
|
else
|
159
|
-
next
|
160
|
-
conditions_hash[
|
222
|
+
next if object.meaningless_value?
|
223
|
+
conditions_hash[name] = object.value
|
161
224
|
end
|
162
225
|
end
|
163
226
|
conditions_hash
|
@@ -172,62 +235,150 @@ module Searchgasm
|
|
172
235
|
|
173
236
|
self.class.class_eval <<-"end_eval", __FILE__, __LINE__
|
174
237
|
def #{association.name}
|
175
|
-
if
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
objects << @#{association.name}
|
238
|
+
if objects[:#{association.name}].nil?
|
239
|
+
objects[:#{association.name}] = Searchgasm::Conditions::Base.create_virtual_class(#{association.class_name}).new
|
240
|
+
objects[:#{association.name}].relationship_name = "#{association.name}"
|
241
|
+
objects[:#{association.name}].protect = protect
|
180
242
|
end
|
181
|
-
|
243
|
+
objects[:#{association.name}]
|
182
244
|
end
|
183
245
|
|
184
246
|
def #{association.name}=(conditions); @conditions = nil; #{association.name}.conditions = conditions; end
|
185
|
-
def reset_#{association.name}!; objects.delete(
|
247
|
+
def reset_#{association.name}!; objects.delete(:#{association.name}); end
|
186
248
|
end_eval
|
187
249
|
end
|
188
250
|
|
189
251
|
self.class.added_associations = true
|
190
252
|
end
|
191
253
|
|
192
|
-
def
|
193
|
-
|
254
|
+
def extract_column_and_condition_from_method_name(name)
|
255
|
+
name_parts = name.gsub("=", "").split("_")
|
194
256
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
257
|
+
condition_parts = []
|
258
|
+
column = nil
|
259
|
+
while column.nil? && name_parts.size > 0
|
260
|
+
possible_column_name = name_parts.join("_")
|
261
|
+
|
262
|
+
self.class.column_details.each do |column_detail|
|
263
|
+
if column_detail[:column].name == possible_column_name || column_detail[:aliases].include?(possible_column_name)
|
264
|
+
column = column_detail
|
265
|
+
break
|
266
|
+
end
|
201
267
|
end
|
268
|
+
|
269
|
+
condition_parts << name_parts.pop if !column
|
202
270
|
end
|
203
271
|
|
204
|
-
|
272
|
+
return if column.nil?
|
273
|
+
|
274
|
+
condition_name = condition_parts.reverse.join("_")
|
275
|
+
condition = nil
|
276
|
+
|
277
|
+
# Find the real condition
|
278
|
+
self.class.conditions.each do |condition_klass|
|
279
|
+
if condition_klass.condition_names_for_column.include?(condition_name)
|
280
|
+
condition = condition_klass
|
281
|
+
break
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
[column, condition]
|
205
286
|
end
|
206
287
|
|
207
|
-
def
|
288
|
+
def breakdown_method_name(name)
|
289
|
+
column_detail, condition_klass = extract_column_and_condition_from_method_name(name)
|
290
|
+
if !column_detail.nil? && !condition_klass.nil?
|
291
|
+
# There were no modifiers
|
292
|
+
return [[], column_detail, condition_klass]
|
293
|
+
else
|
294
|
+
# There might be modifiers
|
295
|
+
name_parts = name.split("_of_")
|
296
|
+
column_detail, condition_klass = extract_column_and_condition_from_method_name(name_parts.pop)
|
297
|
+
if !column_detail.nil? && !condition_klass.nil?
|
298
|
+
# There were modifiers, lets get their real names
|
299
|
+
modifier_klasses = []
|
300
|
+
name_parts.each do |modifier_name|
|
301
|
+
size_before = modifier_klasses.size
|
302
|
+
self.class.modifiers.each do |modifier_klass|
|
303
|
+
if modifier_klass.modifier_names.include?(modifier_name)
|
304
|
+
modifier_klasses << modifier_klass
|
305
|
+
break
|
306
|
+
end
|
307
|
+
end
|
308
|
+
return if modifier_klasses.size == size_before # there was an invalid modifer, return nil for everything and let it act as a nomethoderror
|
309
|
+
end
|
310
|
+
|
311
|
+
return [modifier_klasses, column_detail, condition_klass]
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
nil
|
316
|
+
end
|
317
|
+
|
318
|
+
def build_method_name(modifier_klasses, column_name, condition_name)
|
319
|
+
modifier_name_parts = []
|
320
|
+
modifier_klasses.each { |modifier_klass| modifier_name_parts << modifier_klass.modifier_names.first }
|
321
|
+
method_name_parts = []
|
322
|
+
method_name_parts << modifier_name_parts.join("_of_") unless modifier_name_parts.blank?
|
323
|
+
method_name_parts << column_name
|
324
|
+
method_name_parts << condition_name
|
325
|
+
method_name_parts.join("_")
|
326
|
+
end
|
327
|
+
|
328
|
+
def method_missing(name, *args, &block)
|
329
|
+
modifier_klasses, column_detail, condition_klass = breakdown_method_name(name.to_s)
|
330
|
+
if !column_detail.nil? && !condition_klass.nil?
|
331
|
+
method_name = build_method_name(modifier_klasses, column_detail[:column].name, condition_klass.condition_names_for_column.first)
|
332
|
+
column_type = column_sql = nil
|
333
|
+
if !modifier_klasses.blank?
|
334
|
+
# Find the column type
|
335
|
+
column_type = modifier_klasses.first.return_type
|
336
|
+
|
337
|
+
# Build the column sql
|
338
|
+
column_sql = "#{klass.connection.quote_table_name(klass.table_name)}.#{klass.connection.quote_column_name(column_detail[:column].name)}"
|
339
|
+
modifier_klasses.each do |modifier_klass|
|
340
|
+
next unless klass.connection.respond_to?(modifier_klass.adapter_method_name)
|
341
|
+
column_sql = klass.connection.send(modifier_klass.adapter_method_name, column_sql)
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
add_condition!(condition_klass, method_name, column_detail[:column], column_type, column_sql)
|
346
|
+
|
347
|
+
([column_detail[:column].name] + column_detail[:aliases]).each do |column_name|
|
348
|
+
condition_klass.condition_names_for_column.each do |condition_name|
|
349
|
+
alias_method_name = build_method_name(modifier_klasses, column_name, condition_name)
|
350
|
+
add_condition_alias!(alias_method_name, method_name) unless alias_method_name == method_name
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
send(method_name + (name.to_s =~ /=$/ ? "=" : ""), *args, &block)
|
355
|
+
else
|
356
|
+
super
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
def add_condition!(condition, name, column = nil, column_type = nil, column_sql = nil)
|
208
361
|
self.class.condition_names << name
|
209
362
|
|
210
363
|
self.class.class_eval <<-"end_eval", __FILE__, __LINE__
|
211
364
|
def #{name}_object
|
212
|
-
if
|
213
|
-
|
214
|
-
objects << @#{name}
|
365
|
+
if objects[:#{name}].nil?
|
366
|
+
objects[:#{name}] = #{condition.name}.new(klass, #{column.blank? ? "nil" : "klass.columns_hash['#{column.name}']"}, #{column_type.blank? ? "nil" : "\"#{column_type}\""}, #{column_sql.blank? ? "nil" : "\"#{column_sql.gsub('"', '\"')}\""})
|
215
367
|
end
|
216
|
-
|
368
|
+
objects[:#{name}]
|
217
369
|
end
|
218
370
|
|
219
371
|
def #{name}; #{name}_object.value; end
|
220
372
|
|
221
373
|
def #{name}=(value)
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
end
|
374
|
+
@conditions = nil
|
375
|
+
|
376
|
+
#{name}_object.value = value
|
377
|
+
reset_#{name}! if #{name}_object.meaningless_value?
|
378
|
+
value
|
228
379
|
end
|
229
380
|
|
230
|
-
def reset_#{name}!; objects.delete(
|
381
|
+
def reset_#{name}!; objects.delete(:#{name}); end
|
231
382
|
end_eval
|
232
383
|
end
|
233
384
|
|
@@ -235,38 +386,33 @@ module Searchgasm
|
|
235
386
|
self.class.condition_names << alias_name
|
236
387
|
|
237
388
|
self.class.class_eval do
|
389
|
+
alias_method "#{alias_name}_object", "#{name}_object"
|
238
390
|
alias_method alias_name, name
|
239
391
|
alias_method "#{alias_name}=", "#{name}="
|
392
|
+
alias_method "reset_#{alias_name}!", "reset_#{name}!"
|
240
393
|
end
|
241
394
|
end
|
242
395
|
|
243
|
-
def add_klass_conditions!
|
244
|
-
return true if self.class.added_klass_conditions
|
245
|
-
|
246
|
-
self.class.conditions.each do |condition|
|
247
|
-
name = condition.name_for_klass(klass)
|
248
|
-
next if name.blank?
|
249
|
-
add_condition!(condition, name)
|
250
|
-
condition.aliases_for_klass(klass).each { |alias_name| add_condition_alias!(alias_name, name) }
|
251
|
-
end
|
252
|
-
|
253
|
-
self.class.added_klass_conditions = true
|
254
|
-
end
|
255
|
-
|
256
396
|
def assert_valid_conditions(conditions)
|
257
|
-
conditions.
|
397
|
+
conditions.each do |condition, value|
|
398
|
+
raise(ArgumentError, "The #{condition} condition is not a valid condition") if !(self.class.condition_names + self.class.association_names + ["any"]).include?(condition.to_s) && respond_to?(condition)
|
399
|
+
end
|
258
400
|
end
|
259
401
|
|
260
402
|
def associations
|
261
|
-
|
403
|
+
associations = {}
|
404
|
+
objects.each do |name, object|
|
405
|
+
associations[name] = object if object.class < ::Searchgasm::Conditions::Base
|
406
|
+
end
|
407
|
+
associations
|
262
408
|
end
|
263
409
|
|
264
410
|
def objects
|
265
|
-
@objects ||=
|
411
|
+
@objects ||= {}
|
266
412
|
end
|
267
413
|
|
268
414
|
def reset_objects!
|
269
|
-
objects.each { |object| object.class < ::Searchgasm::Conditions::Base ? eval("@#{object.relationship_name} = nil") : eval("@#{
|
415
|
+
objects.each { |name, object| object.class < ::Searchgasm::Conditions::Base ? eval("@#{object.relationship_name} = nil") : eval("@#{name} = nil") }
|
270
416
|
objects.clear
|
271
417
|
end
|
272
418
|
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Searchgasm
|
2
|
+
module Modifiers
|
3
|
+
class Base
|
4
|
+
class << self
|
5
|
+
# A convenience method for the name of this modifier
|
6
|
+
def modifier_name
|
7
|
+
name.split("::").last.underscore
|
8
|
+
end
|
9
|
+
|
10
|
+
# The various names for the modifier. The first in the array is the "main" name, the rest are just aliases to the "main" name
|
11
|
+
def modifier_names
|
12
|
+
[modifier_name]
|
13
|
+
end
|
14
|
+
|
15
|
+
# The method in the connection adapter that creates the SQL for the modifier
|
16
|
+
def adapter_method_name
|
17
|
+
"#{modifier_name}_sql"
|
18
|
+
end
|
19
|
+
|
20
|
+
# The type of value returned from the SQL. A class the extends this MUST define this method.
|
21
|
+
def return_type
|
22
|
+
raise "You did not specify a return type for the #{modifier_name} modifier. Please specify if it is an :integer, :string, etc."
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|