searchgasm 1.2.2 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|