meta_search_hub 1.1.3
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.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/.gitmodules +6 -0
- data/CHANGELOG +109 -0
- data/Gemfile +12 -0
- data/LICENSE +20 -0
- data/README.rdoc +438 -0
- data/Rakefile +69 -0
- data/VERSION +1 -0
- data/lib/meta_search/builder.rb +316 -0
- data/lib/meta_search/exceptions.rb +17 -0
- data/lib/meta_search/helpers/form_builder.rb +166 -0
- data/lib/meta_search/helpers/form_helper.rb +24 -0
- data/lib/meta_search/helpers/url_helper.rb +66 -0
- data/lib/meta_search/helpers.rb +3 -0
- data/lib/meta_search/locale/en.yml +24 -0
- data/lib/meta_search/method.rb +129 -0
- data/lib/meta_search/model_compatibility.rb +75 -0
- data/lib/meta_search/searches/active_record.rb +203 -0
- data/lib/meta_search/utility.rb +110 -0
- data/lib/meta_search/where.rb +264 -0
- data/lib/meta_search.rb +58 -0
- data/meta_search.gemspec +90 -0
- data/test/fixtures/companies.yml +17 -0
- data/test/fixtures/company.rb +22 -0
- data/test/fixtures/data_type.rb +5 -0
- data/test/fixtures/data_types.yml +15 -0
- data/test/fixtures/developer.rb +11 -0
- data/test/fixtures/developers.yml +62 -0
- data/test/fixtures/developers_projects.yml +25 -0
- data/test/fixtures/note.rb +3 -0
- data/test/fixtures/notes.yml +79 -0
- data/test/fixtures/project.rb +4 -0
- data/test/fixtures/projects.yml +34 -0
- data/test/fixtures/schema.rb +47 -0
- data/test/helper.rb +44 -0
- data/test/locales/es.yml +5 -0
- data/test/locales/flanders.yml +18 -0
- data/test/test_search.rb +969 -0
- data/test/test_view_helpers.rb +447 -0
- metadata +160 -0
data/test/test_search.rb
ADDED
|
@@ -0,0 +1,969 @@
|
|
|
1
|
+
require 'helper'
|
|
2
|
+
|
|
3
|
+
class TestSearch < Test::Unit::TestCase
|
|
4
|
+
|
|
5
|
+
context "A Company search where options[:user] = 'blocked'" do
|
|
6
|
+
setup do
|
|
7
|
+
@s = Company.search({}, :user => 'blocked')
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
should "not respond_to? a search against backwards_name" do
|
|
11
|
+
assert !@s.respond_to?(:backwards_name), "The search responded to :backwards_name"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
should "raise an error if we try to search on backwards_name" do
|
|
15
|
+
assert_raise NoMethodError do
|
|
16
|
+
@s.backwards_name = 'blah'
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
should "not respond_to? a search against updated_at_eq" do
|
|
21
|
+
assert !@s.respond_to?(:updated_at_eq), "The search responded to :updated_at_eq"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
should "raise an error if we try to search on updated_at" do
|
|
25
|
+
assert_raise NoMethodError do
|
|
26
|
+
@s.updated_at_eq = 'blah'
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
should "not respond_to? a search against notes_note_matches" do
|
|
31
|
+
assert !@s.respond_to?(:notes_note_matches), "The search responded to :notes_note_matches"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
should "raise an error if we try to search on notes_note_matches" do
|
|
35
|
+
assert_raise NoMethodError do
|
|
36
|
+
@s.notes_note_matches = '%blah%'
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
context "A Developer search where options[:user] = 'privileged'" do
|
|
42
|
+
setup do
|
|
43
|
+
@s = Developer.search({}, :user => 'privileged')
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
should "respond_to? a search against name_eq" do
|
|
47
|
+
assert_respond_to @s, :name_eq
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
should "not raise an error on a search against name_eq" do
|
|
51
|
+
assert_nothing_raised do
|
|
52
|
+
@s.name_eq = 'blah'
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
should "respond_to? a search against company_name_eq" do
|
|
57
|
+
assert_respond_to @s, :company_name_eq
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
should "not raise an error on a search against name_eq" do
|
|
61
|
+
assert_nothing_raised do
|
|
62
|
+
@s.company_name_eq = 'blah'
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
should "respond_to? a search against company_updated_at_eq" do
|
|
67
|
+
assert_respond_to @s, :company_updated_at_eq
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
should "not raise an error on a search against company_updated_at_eq" do
|
|
71
|
+
assert_nothing_raised do
|
|
72
|
+
@s.company_updated_at_eq = Time.now
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
context "A Developer search" do
|
|
78
|
+
setup do
|
|
79
|
+
@s = Developer.search({:name_equals=>"Forgetful Notetaker"})
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
context "without any opts" do
|
|
83
|
+
should "find a null entry when searching notes" do
|
|
84
|
+
assert_equal 1, @s.notes_note_is_null(true).all.size
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
should "find no non-null entry when searching notes" do
|
|
88
|
+
assert_equal 0, @s.notes_note_is_not_null(true).all.size
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
context "with outer join specified" do
|
|
93
|
+
setup do
|
|
94
|
+
@s = Developer.search({:name_equals => "Forgetful Notetaker"}, :join_type => :outer)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
should "find a null entry when searching notes" do
|
|
98
|
+
assert_equal 1, @s.notes_note_is_null(true).all.size
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
should "find no non-null entry when searching notes" do
|
|
102
|
+
assert_equal 0, @s.notes_note_is_not_null(true).all.size
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
context "with inner join specified" do
|
|
107
|
+
setup do
|
|
108
|
+
@s = Developer.search({:name_equals=>"Forgetful Notetaker"}, :join_type => :inner)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
should "find no null entry when searching notes" do
|
|
112
|
+
assert_equal 0, @s.notes_note_is_null(true).all.size
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
should "find no non-null entry when searching notes" do
|
|
116
|
+
assert_equal 0, @s.notes_note_is_not_null(true).all.size
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
[{:name => 'Company', :object => Company},
|
|
124
|
+
{:name => 'Company as a Relation', :object => Company.scoped}].each do |object|
|
|
125
|
+
context_a_search_against object[:name], object[:object] do
|
|
126
|
+
should "have a relation attribute which is an ActiveRecord::Relation" do
|
|
127
|
+
assert_equal ActiveRecord::Relation, @s.relation.class
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
should "have a base attribute which is a Class inheriting from ActiveRecord::Base" do
|
|
131
|
+
assert_equal Company, @s.base
|
|
132
|
+
assert_contains @s.base.ancestors, ActiveRecord::Base
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
should "have an association named developers" do
|
|
136
|
+
assert @s.get_association(:developers)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
should "respond_to? a search against a developer attribute" do
|
|
140
|
+
assert_respond_to @s, :developers_name_eq
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
should "have a column named name" do
|
|
144
|
+
assert @s.get_column(:name)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
should "respond_to? a search against name" do
|
|
148
|
+
assert_respond_to @s, :name_eq
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
should "respond_to? a search against backwards_name" do
|
|
152
|
+
assert_respond_to @s, :backwards_name
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
should "exclude the column named updated_at" do
|
|
156
|
+
assert_nil @s.get_column(:updated_at)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
should "not respond_to? updated_at" do
|
|
160
|
+
assert !@s.respond_to?(:updated_at), "The search responded to :updated_at"
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
should "raise an error if we try to search on updated_at" do
|
|
164
|
+
assert_raise NoMethodError do
|
|
165
|
+
@s.updated_at_eq = [2009, 1, 1]
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
should "exclude the association named notes" do
|
|
170
|
+
assert_nil @s.get_association(:notes)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
should "not respond_to? notes_note_eq" do
|
|
174
|
+
assert !@s.respond_to?(:notes_note_eq), "The search responded to :notes_note_eq"
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
should "raise an error if we try to search on notes" do
|
|
178
|
+
assert_raise NoMethodError do
|
|
179
|
+
@s.notes_note_eq = 'Blah'
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
should "honor its associations' excluded attributes" do
|
|
184
|
+
assert_nil @s.get_attribute(:data_types_str)
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
should "not respond_to? data_types_str_eq" do
|
|
188
|
+
assert !@s.respond_to?(:data_types_str_eq), "The search responded to :data_types_str_eq"
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
should "respond_to? data_types_bln_eq" do
|
|
192
|
+
assert_respond_to @s, :data_types_bln_eq
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
should "raise an error if we try to search data_types.str" do
|
|
196
|
+
assert_raise NoMethodError do
|
|
197
|
+
@s.data_types_str_eq = 'Blah'
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
should "raise an error when MAX_JOIN_DEPTH is exceeded" do
|
|
202
|
+
assert_raise MetaSearch::JoinDepthError do
|
|
203
|
+
@s.developers_company_developers_company_developers_name_equals = "Ernie Miller"
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
context "when meta_sort value is empty string" do
|
|
208
|
+
setup do
|
|
209
|
+
@s.meta_sort = ''
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
should "not raise an error, just ignore sorting" do
|
|
213
|
+
assert_nothing_raised do
|
|
214
|
+
assert_equal Company.all, @s.all
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
should "sort by name in ascending order" do
|
|
220
|
+
@s.meta_sort = 'name.asc'
|
|
221
|
+
assert_equal Company.order('name asc').all,
|
|
222
|
+
@s.all
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
should "sort by name in ascending order as a method call" do
|
|
226
|
+
@s.meta_sort 'name.asc'
|
|
227
|
+
assert_equal Company.order('name asc').all,
|
|
228
|
+
@s.all
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
should "sort by name in descending order" do
|
|
232
|
+
@s.meta_sort = 'name.desc'
|
|
233
|
+
assert_equal Company.order('name desc').all,
|
|
234
|
+
@s.all
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
context "where name contains optical" do
|
|
238
|
+
setup do
|
|
239
|
+
@s.name_contains = 'optical'
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
should "return one result" do
|
|
243
|
+
assert_equal 1, @s.all.size
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
should "return a company named Advanced Optical Solutions" do
|
|
247
|
+
assert_contains @s.all, Company.where(:name => 'Advanced Optical Solutions').first
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
should "not return a company named Initech" do
|
|
251
|
+
assert_does_not_contain @s.all, Company.where(:name => "Initech").first
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
context "where name contains optical as a method call" do
|
|
256
|
+
setup do
|
|
257
|
+
@s.name_contains 'optical'
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
should "return one result" do
|
|
261
|
+
assert_equal 1, @s.all.size
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
should "return a company named Advanced Optical Solutions" do
|
|
265
|
+
assert_contains @s.all, Company.where(:name => 'Advanced Optical Solutions').first
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
should "not return a company named Initech" do
|
|
269
|
+
assert_does_not_contain @s.all, Company.where(:name => "Initech").first
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
context "where developer name starts with Ernie" do
|
|
274
|
+
setup do
|
|
275
|
+
@s.developers_name_starts_with = 'Ernie'
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
should "return one result" do
|
|
279
|
+
assert_equal 1, @s.all.size
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
should "return a company named Mission Data" do
|
|
283
|
+
assert_contains @s.all, Company.where(:name => 'Mission Data').first
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
should "not return a company named Initech" do
|
|
287
|
+
assert_does_not_contain @s.all, Company.where(:name => "Initech").first
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
context "and slackers salary is greater than $70k" do
|
|
291
|
+
setup do
|
|
292
|
+
@s.slackers_salary_gt = 70000
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
should "return no results" do
|
|
296
|
+
assert_equal 0, @s.all.size
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
should "join developers twice" do
|
|
300
|
+
assert @s.to_sql.match(/join\s+"?developers"?.*join\s+"?developers"?/i)
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
should "alias the second join of developers" do
|
|
304
|
+
assert @s.to_sql.match(/join\s+"?developers"?\s+"?slackers_companies"?/i)
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
context "where developer note indicates he will crack yo skull" do
|
|
310
|
+
setup do
|
|
311
|
+
@s.developer_notes_note_equals = "Will show you what he's doing."
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
should "return one result" do
|
|
315
|
+
assert_equal 1, @s.all.size
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
should "return a company named Advanced Optical Solutions" do
|
|
319
|
+
assert_contains @s.all, Company.where(:name => 'Advanced Optical Solutions').first
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
should "not return a company named Mission Data" do
|
|
323
|
+
assert_does_not_contain @s.all, Company.where(:name => "Mission Data").first
|
|
324
|
+
end
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
context "where developer note indicates he will crack yo skull through two associations" do
|
|
328
|
+
setup do
|
|
329
|
+
@s.developers_notes_note_equals = "Will show you what he's doing."
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
should "return one result" do
|
|
333
|
+
assert_equal 1, @s.all.size
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
should "return a company named Advanced Optical Solutions" do
|
|
337
|
+
assert_contains @s.all, Company.where(:name => 'Advanced Optical Solutions').first
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
should "not return a company named Mission Data" do
|
|
341
|
+
assert_does_not_contain @s.all, Company.where(:name => "Mission Data").first
|
|
342
|
+
end
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
context "where developer note indicates he will crack yo skull through four associations" do
|
|
346
|
+
setup do
|
|
347
|
+
@s.developers_company_developers_notes_note_equals = "Will show you what he's doing."
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
should "return two results, one of which is a duplicate due to joins" do
|
|
351
|
+
assert_equal 2, @s.all.size
|
|
352
|
+
assert_equal 1, @s.all.uniq.size
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
should "return a company named Advanced Optical Solutions" do
|
|
356
|
+
assert_contains @s.all, Company.where(:name => 'Advanced Optical Solutions').first
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
should "not return a company named Mission Data" do
|
|
360
|
+
assert_does_not_contain @s.all, Company.where(:name => "Mission Data").first
|
|
361
|
+
end
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
context "where backwards name is hcetinI as a method call" do
|
|
365
|
+
setup do
|
|
366
|
+
@s.backwards_name 'hcetinI'
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
should "return 1 result" do
|
|
370
|
+
assert_equal 1, @s.all.size
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
should "return a company named Initech" do
|
|
374
|
+
assert_contains @s.all, Company.where(:name => 'Initech').first
|
|
375
|
+
end
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
context "where backwards name is hcetinI" do
|
|
379
|
+
setup do
|
|
380
|
+
@s.backwards_name = 'hcetinI'
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
should "return 1 result" do
|
|
384
|
+
assert_equal 1, @s.all.size
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
should "return a company named Initech" do
|
|
388
|
+
assert_contains @s.all, Company.where(:name => 'Initech').first
|
|
389
|
+
end
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
context "where with_slackers_by_name_and_salary_range is sent an array with 3 values" do
|
|
393
|
+
setup do
|
|
394
|
+
@s.with_slackers_by_name_and_salary_range = ['Peter Gibbons', 90000, 110000]
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
should "return 1 result" do
|
|
398
|
+
assert_equal 1, @s.all.size
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
should "return a company named Initech" do
|
|
402
|
+
assert_contains @s.all, Company.where(:name => 'Initech').first
|
|
403
|
+
end
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
should "raise an error when the wrong number of parameters would be supplied to a custom search" do
|
|
407
|
+
assert_raise ArgumentError do
|
|
408
|
+
@s.with_slackers_by_name_and_salary_range = ['Peter Gibbons', 90000]
|
|
409
|
+
end
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
should "raise an error when a custom search method does not return a relation" do
|
|
413
|
+
assert_raise MetaSearch::NonRelationReturnedError do
|
|
414
|
+
@s.backwards_name_as_string = 'hcetinI'
|
|
415
|
+
end
|
|
416
|
+
end
|
|
417
|
+
end
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
[{:name => 'Developer', :object => Developer},
|
|
421
|
+
{:name => 'Developer as a Relation', :object => Developer.scoped}].each do |object|
|
|
422
|
+
context_a_search_against object[:name], object[:object] do
|
|
423
|
+
should "exclude the column named company_id" do
|
|
424
|
+
assert_nil @s.get_column(:company_id)
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
should "have an association named projects" do
|
|
428
|
+
assert @s.get_association(:projects)
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
context "sorted by company name in ascending order" do
|
|
432
|
+
setup do
|
|
433
|
+
@s.meta_sort = 'company_name.asc'
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
should "sort by company name in ascending order" do
|
|
437
|
+
assert_equal Developer.joins(:company).order('companies.name asc').all,
|
|
438
|
+
@s.all
|
|
439
|
+
end
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
context "sorted by company name in descending order" do
|
|
443
|
+
setup do
|
|
444
|
+
@s.meta_sort = 'company_name.desc'
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
should "sort by company name in descending order" do
|
|
448
|
+
assert_equal Developer.joins(:company).order('companies.name desc').all,
|
|
449
|
+
@s.all
|
|
450
|
+
end
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
context "sorted by salary and name in descending order" do
|
|
454
|
+
setup do
|
|
455
|
+
@s.meta_sort = 'salary_and_name.desc'
|
|
456
|
+
end
|
|
457
|
+
|
|
458
|
+
should "sort by salary and name in descending order" do
|
|
459
|
+
assert_equal Developer.order('salary DESC, name DESC').all,
|
|
460
|
+
@s.all
|
|
461
|
+
end
|
|
462
|
+
end
|
|
463
|
+
|
|
464
|
+
context "where developer is Bob-approved" do
|
|
465
|
+
setup do
|
|
466
|
+
@s.notes_note_equals = "A straight shooter with upper management written all over him."
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
should "return Peter Gibbons" do
|
|
470
|
+
assert_contains @s.all, Developer.where(:name => 'Peter Gibbons').first
|
|
471
|
+
end
|
|
472
|
+
end
|
|
473
|
+
|
|
474
|
+
context "where name or company name starts with m" do
|
|
475
|
+
setup do
|
|
476
|
+
@s.name_or_company_name_starts_with = "m"
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
should "return Michael Bolton and all employees of Mission Data" do
|
|
480
|
+
assert_equal @s.all, Developer.where(:name => 'Michael Bolton').all +
|
|
481
|
+
Company.where(:name => 'Mission Data').first.developers
|
|
482
|
+
end
|
|
483
|
+
end
|
|
484
|
+
|
|
485
|
+
context "where name ends with Miller" do
|
|
486
|
+
setup do
|
|
487
|
+
@s.name_ends_with = 'Miller'
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
should "return one result" do
|
|
491
|
+
assert_equal 1, @s.all.size
|
|
492
|
+
end
|
|
493
|
+
|
|
494
|
+
should "return a developer named Ernie Miller" do
|
|
495
|
+
assert_contains @s.all, Developer.where(:name => 'Ernie Miller').first
|
|
496
|
+
end
|
|
497
|
+
|
|
498
|
+
should "not return a developer named Herb Myers" do
|
|
499
|
+
assert_does_not_contain @s.all, Developer.where(:name => "Herb Myers").first
|
|
500
|
+
end
|
|
501
|
+
end
|
|
502
|
+
|
|
503
|
+
context "where name starts with any of Ernie, Herb, or Peter" do
|
|
504
|
+
setup do
|
|
505
|
+
@s.name_starts_with_any = ['Ernie', 'Herb', 'Peter']
|
|
506
|
+
end
|
|
507
|
+
|
|
508
|
+
should "return three results" do
|
|
509
|
+
assert_equal 3, @s.all.size
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
should "return a developer named Ernie Miller" do
|
|
513
|
+
assert_contains @s.all, Developer.where(:name => 'Ernie Miller').first
|
|
514
|
+
end
|
|
515
|
+
|
|
516
|
+
should "not return a developer named Samir Nagheenanajar" do
|
|
517
|
+
assert_does_not_contain @s.all, Developer.where(:name => "Samir Nagheenanajar").first
|
|
518
|
+
end
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
context "where name does not equal Ernie Miller" do
|
|
522
|
+
setup do
|
|
523
|
+
@s.name_ne = 'Ernie Miller'
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
should "return eight results" do
|
|
527
|
+
assert_equal 8, @s.all.size
|
|
528
|
+
end
|
|
529
|
+
|
|
530
|
+
should "not return a developer named Ernie Miller" do
|
|
531
|
+
assert_does_not_contain @s.all, Developer.where(:name => "Ernie Miller").first
|
|
532
|
+
end
|
|
533
|
+
end
|
|
534
|
+
|
|
535
|
+
context "where name contains all of a, e, and i" do
|
|
536
|
+
setup do
|
|
537
|
+
@s.name_contains_all = ['a', 'e', 'i']
|
|
538
|
+
end
|
|
539
|
+
|
|
540
|
+
should "return two results" do
|
|
541
|
+
assert_equal 2, @s.all.size
|
|
542
|
+
end
|
|
543
|
+
|
|
544
|
+
should "return a developer named Samir Nagheenanajar" do
|
|
545
|
+
assert_contains @s.all, Developer.where(:name => "Samir Nagheenanajar").first
|
|
546
|
+
end
|
|
547
|
+
|
|
548
|
+
should "not return a developer named Ernie Miller" do
|
|
549
|
+
assert_does_not_contain @s.all, Developer.where(:name => 'Ernie Miller').first
|
|
550
|
+
end
|
|
551
|
+
end
|
|
552
|
+
|
|
553
|
+
context "where project estimated hours are greater than or equal to 1000" do
|
|
554
|
+
setup do
|
|
555
|
+
@s.projects_estimated_hours_gte = 1000
|
|
556
|
+
end
|
|
557
|
+
|
|
558
|
+
should "return three results" do
|
|
559
|
+
assert_equal 3, @s.all.size
|
|
560
|
+
end
|
|
561
|
+
|
|
562
|
+
should "return these developers" do
|
|
563
|
+
assert_same_elements @s.all.collect {|d| d.name},
|
|
564
|
+
['Peter Gibbons', 'Michael Bolton', 'Samir Nagheenanajar']
|
|
565
|
+
end
|
|
566
|
+
end
|
|
567
|
+
|
|
568
|
+
context "where project estimated hours are greater than 1000" do
|
|
569
|
+
setup do
|
|
570
|
+
@s.projects_estimated_hours_gt = 1000
|
|
571
|
+
end
|
|
572
|
+
|
|
573
|
+
should "return no results" do
|
|
574
|
+
assert_equal 0, @s.all.size
|
|
575
|
+
end
|
|
576
|
+
end
|
|
577
|
+
|
|
578
|
+
context "where developer is named Ernie Miller by polymorphic belongs_to against an association" do
|
|
579
|
+
setup do
|
|
580
|
+
@s.notes_notable_developer_type_name_equals = "Ernie Miller"
|
|
581
|
+
end
|
|
582
|
+
|
|
583
|
+
should "return one result" do
|
|
584
|
+
assert_equal 1, @s.all.size
|
|
585
|
+
end
|
|
586
|
+
|
|
587
|
+
should "return a developer named Ernie Miller" do
|
|
588
|
+
assert_contains @s.all, Developer.where(:name => 'Ernie Miller').first
|
|
589
|
+
end
|
|
590
|
+
|
|
591
|
+
should "not return a developer named Herb Myers" do
|
|
592
|
+
assert_does_not_contain @s.all, Developer.where(:name => "Herb Myers").first
|
|
593
|
+
end
|
|
594
|
+
end
|
|
595
|
+
end
|
|
596
|
+
end
|
|
597
|
+
|
|
598
|
+
[{:name => 'DataType', :object => DataType},
|
|
599
|
+
{:name => 'DataType as a Relation', :object => DataType.scoped}].each do |object|
|
|
600
|
+
context_a_search_against object[:name], object[:object] do
|
|
601
|
+
should "raise an error on a contains search against a boolean column" do
|
|
602
|
+
assert_raise NoMethodError do
|
|
603
|
+
@s.bln_contains = "true"
|
|
604
|
+
end
|
|
605
|
+
end
|
|
606
|
+
|
|
607
|
+
context "where boolean column equals true" do
|
|
608
|
+
setup do
|
|
609
|
+
@s.bln_equals = true
|
|
610
|
+
end
|
|
611
|
+
|
|
612
|
+
should "return five results" do
|
|
613
|
+
assert_equal 5, @s.all.size
|
|
614
|
+
end
|
|
615
|
+
|
|
616
|
+
should "contain no results with a false boolean column" do
|
|
617
|
+
assert_does_not_contain @s.all.collect {|r| r.bln}, false
|
|
618
|
+
end
|
|
619
|
+
end
|
|
620
|
+
|
|
621
|
+
context "where boolean column is_true" do
|
|
622
|
+
setup do
|
|
623
|
+
@s.bln_is_true = true
|
|
624
|
+
end
|
|
625
|
+
|
|
626
|
+
should "return five results" do
|
|
627
|
+
assert_equal 5, @s.all.size
|
|
628
|
+
end
|
|
629
|
+
|
|
630
|
+
should "contain no results with a false boolean column" do
|
|
631
|
+
assert_does_not_contain @s.all.collect {|r| r.bln}, false
|
|
632
|
+
end
|
|
633
|
+
end
|
|
634
|
+
|
|
635
|
+
context "where boolean column equals false" do
|
|
636
|
+
setup do
|
|
637
|
+
@s.bln_equals = false
|
|
638
|
+
end
|
|
639
|
+
|
|
640
|
+
should "return four results" do
|
|
641
|
+
assert_equal 4, @s.all.size
|
|
642
|
+
end
|
|
643
|
+
|
|
644
|
+
should "contain no results with a true boolean column" do
|
|
645
|
+
assert_does_not_contain @s.all.collect {|r| r.bln}, true
|
|
646
|
+
end
|
|
647
|
+
end
|
|
648
|
+
|
|
649
|
+
context "where boolean column is_false" do
|
|
650
|
+
setup do
|
|
651
|
+
@s.bln_is_false = true
|
|
652
|
+
end
|
|
653
|
+
|
|
654
|
+
should "return four results" do
|
|
655
|
+
assert_equal 4, @s.all.size
|
|
656
|
+
end
|
|
657
|
+
|
|
658
|
+
should "contain no results with a true boolean column" do
|
|
659
|
+
assert_does_not_contain @s.all.collect {|r| r.bln}, true
|
|
660
|
+
end
|
|
661
|
+
end
|
|
662
|
+
|
|
663
|
+
context "where date column is Christmas 2009 by array" do
|
|
664
|
+
setup do
|
|
665
|
+
@s.dat_equals = [2009, 12, 25]
|
|
666
|
+
end
|
|
667
|
+
|
|
668
|
+
should "return one result" do
|
|
669
|
+
assert_equal 1, @s.all.size
|
|
670
|
+
end
|
|
671
|
+
|
|
672
|
+
should "contain a result with Christmas 2009 as its date" do
|
|
673
|
+
assert_equal Date.parse('2009/12/25'), @s.first.dat
|
|
674
|
+
end
|
|
675
|
+
end
|
|
676
|
+
|
|
677
|
+
context "where date column is Christmas 2009 by Date object" do
|
|
678
|
+
setup do
|
|
679
|
+
@s.dat_equals = Date.new(2009, 12, 25)
|
|
680
|
+
end
|
|
681
|
+
|
|
682
|
+
should "return one result" do
|
|
683
|
+
assert_equal 1, @s.all.size
|
|
684
|
+
end
|
|
685
|
+
|
|
686
|
+
should "contain a result with Christmas 2009 as its date" do
|
|
687
|
+
assert_equal Date.parse('2009/12/25'), @s.first.dat
|
|
688
|
+
end
|
|
689
|
+
end
|
|
690
|
+
|
|
691
|
+
context "where time column is > 1:00 PM and < 3:30 PM" do
|
|
692
|
+
setup do
|
|
693
|
+
@s.tim_gt = Time.parse('2000-01-01 13:00') # Rails "dummy time" format
|
|
694
|
+
@s.tim_lt = Time.parse('2000-01-01 15:30') # Rails "dummy time" format
|
|
695
|
+
end
|
|
696
|
+
|
|
697
|
+
should "return three results" do
|
|
698
|
+
assert_equal 3, @s.all.size
|
|
699
|
+
end
|
|
700
|
+
|
|
701
|
+
should "not contain results with time column before or after constraints" do
|
|
702
|
+
assert_equal [], @s.all.select {|r|
|
|
703
|
+
r.tim < Time.parse('2000-01-01 13:00') || r.tim > Time.parse('2000-01-01 15:30')
|
|
704
|
+
}
|
|
705
|
+
end
|
|
706
|
+
end
|
|
707
|
+
|
|
708
|
+
context "where timestamp column is in the year 2010" do
|
|
709
|
+
setup do
|
|
710
|
+
@s.tms_gte = Time.utc(2010, 1, 1)
|
|
711
|
+
end
|
|
712
|
+
|
|
713
|
+
should "return two results" do
|
|
714
|
+
assert_equal 2, @s.all.size
|
|
715
|
+
end
|
|
716
|
+
|
|
717
|
+
should "not contain results with timestamp column before 2010" do
|
|
718
|
+
assert_equal [], @s.all.select {|r|
|
|
719
|
+
r.tms < Time.utc(2010, 1, 1)
|
|
720
|
+
}
|
|
721
|
+
end
|
|
722
|
+
end
|
|
723
|
+
|
|
724
|
+
context "where timestamp column is before the year 2010" do
|
|
725
|
+
setup do
|
|
726
|
+
@s.tms_lt = Time.utc(2010, 1, 1)
|
|
727
|
+
end
|
|
728
|
+
|
|
729
|
+
should "return seven results" do
|
|
730
|
+
assert_equal 7, @s.all.size
|
|
731
|
+
end
|
|
732
|
+
|
|
733
|
+
should "not contain results with timestamp in 2010" do
|
|
734
|
+
assert_equal [], @s.all.select {|r|
|
|
735
|
+
r.tms >= Time.utc(2010, 1, 1)
|
|
736
|
+
}
|
|
737
|
+
end
|
|
738
|
+
end
|
|
739
|
+
|
|
740
|
+
context "where decimal column is > 5000" do
|
|
741
|
+
setup do
|
|
742
|
+
@s.dec_gt = 5000
|
|
743
|
+
end
|
|
744
|
+
|
|
745
|
+
should "return four results" do
|
|
746
|
+
assert_equal 4, @s.all.size
|
|
747
|
+
end
|
|
748
|
+
|
|
749
|
+
should "not contain results with decimal column <= 5000" do
|
|
750
|
+
assert_equal [], @s.all.select {|r|
|
|
751
|
+
r.dec <= 5000
|
|
752
|
+
}
|
|
753
|
+
end
|
|
754
|
+
end
|
|
755
|
+
|
|
756
|
+
context "where float column is between 2.5 and 3.5" do
|
|
757
|
+
setup do
|
|
758
|
+
@s.flt_gte = 2.5
|
|
759
|
+
@s.flt_lte = 3.5
|
|
760
|
+
end
|
|
761
|
+
|
|
762
|
+
should "return three results" do
|
|
763
|
+
assert_equal 3, @s.all.size
|
|
764
|
+
end
|
|
765
|
+
|
|
766
|
+
should "not contain results with float column outside constraints" do
|
|
767
|
+
assert_equal [], @s.all.select {|r|
|
|
768
|
+
r.flt < 2.5 || r.flt > 3.5
|
|
769
|
+
}
|
|
770
|
+
end
|
|
771
|
+
end
|
|
772
|
+
|
|
773
|
+
context "where integer column is in the set (1, 8, 729)" do
|
|
774
|
+
setup do
|
|
775
|
+
@s.int_in = [1, 8, 729]
|
|
776
|
+
end
|
|
777
|
+
|
|
778
|
+
should "return three results" do
|
|
779
|
+
assert_equal 3, @s.all.size
|
|
780
|
+
end
|
|
781
|
+
|
|
782
|
+
should "not contain results outside the specified set" do
|
|
783
|
+
assert_equal [], @s.all.select {|r|
|
|
784
|
+
![1, 8, 729].include?(r.int)
|
|
785
|
+
}
|
|
786
|
+
end
|
|
787
|
+
end
|
|
788
|
+
|
|
789
|
+
context "where integer column is not in the set (1, 8, 729)" do
|
|
790
|
+
setup do
|
|
791
|
+
@s.int_not_in = [1, 8, 729]
|
|
792
|
+
end
|
|
793
|
+
|
|
794
|
+
should "return six results" do
|
|
795
|
+
assert_equal 6, @s.all.size
|
|
796
|
+
end
|
|
797
|
+
|
|
798
|
+
should "not contain results outside the specified set" do
|
|
799
|
+
assert_equal [], @s.all.reject {|r|
|
|
800
|
+
![1, 8, 729].include?(r.int)
|
|
801
|
+
}
|
|
802
|
+
end
|
|
803
|
+
end
|
|
804
|
+
end
|
|
805
|
+
end
|
|
806
|
+
|
|
807
|
+
context_a_search_against "a relation with existing criteria and joins",
|
|
808
|
+
Company.where(:name => "Initech").joins(:developers) do
|
|
809
|
+
should "return the same results as a non-searched relation with no search terms" do
|
|
810
|
+
assert_equal Company.where(:name => "Initech").joins(:developers).all, @s.all
|
|
811
|
+
end
|
|
812
|
+
|
|
813
|
+
context "with a search against the joined association's data" do
|
|
814
|
+
setup do
|
|
815
|
+
@s.developers_salary_less_than = 75000
|
|
816
|
+
end
|
|
817
|
+
|
|
818
|
+
should "not ask to join the association twice" do
|
|
819
|
+
assert_equal 1, @s.relation.joins_values.size
|
|
820
|
+
end
|
|
821
|
+
|
|
822
|
+
should "return a filtered result set based on the criteria of the searched relation" do
|
|
823
|
+
assert_equal Company.where(:name => 'Initech').all, @s.all.uniq
|
|
824
|
+
end
|
|
825
|
+
end
|
|
826
|
+
end
|
|
827
|
+
|
|
828
|
+
context_a_search_against "a relation derived from a joined association",
|
|
829
|
+
Company.where(:name => "Initech").first.developers do
|
|
830
|
+
should "not raise an error" do
|
|
831
|
+
assert_nothing_raised do
|
|
832
|
+
@s.all
|
|
833
|
+
end
|
|
834
|
+
end
|
|
835
|
+
|
|
836
|
+
should "return all developers for that company without conditions" do
|
|
837
|
+
assert_equal Company.where(:name => 'Initech').first.developers.all, @s.all
|
|
838
|
+
end
|
|
839
|
+
|
|
840
|
+
should "allow conditions on the search" do
|
|
841
|
+
@s.name_equals = 'Peter Gibbons'
|
|
842
|
+
assert_equal Developer.where(:name => 'Peter Gibbons').first,
|
|
843
|
+
@s.first
|
|
844
|
+
end
|
|
845
|
+
end
|
|
846
|
+
|
|
847
|
+
context_a_search_against "a relation derived from a joined HM:T association",
|
|
848
|
+
Company.where(:name => "Initech").first.developer_notes do
|
|
849
|
+
should "not raise an error" do
|
|
850
|
+
assert_nothing_raised do
|
|
851
|
+
@s.all
|
|
852
|
+
end
|
|
853
|
+
end
|
|
854
|
+
|
|
855
|
+
should "return all developer notes for that company without conditions" do
|
|
856
|
+
assert_equal Company.where(:name => 'Initech').first.developer_notes.all, @s.all
|
|
857
|
+
end
|
|
858
|
+
|
|
859
|
+
should "allow conditions on the search" do
|
|
860
|
+
@s.note_equals = 'A straight shooter with upper management written all over him.'
|
|
861
|
+
assert_equal Note.where(:note => 'A straight shooter with upper management written all over him.').first,
|
|
862
|
+
@s.first
|
|
863
|
+
end
|
|
864
|
+
end
|
|
865
|
+
|
|
866
|
+
[{:name => 'Project', :object => Project},
|
|
867
|
+
{:name => 'Project as a Relation', :object => Project.scoped}].each do |object|
|
|
868
|
+
context_a_search_against object[:name], object[:object] do
|
|
869
|
+
context "where name is present" do
|
|
870
|
+
setup do
|
|
871
|
+
@s.name_is_present = true
|
|
872
|
+
end
|
|
873
|
+
|
|
874
|
+
should "return 5 results" do
|
|
875
|
+
assert_equal 5, @s.all.size
|
|
876
|
+
end
|
|
877
|
+
|
|
878
|
+
should "contain no results with a blank name column" do
|
|
879
|
+
assert_equal 0, @s.all.select {|r| r.name.blank?}.size
|
|
880
|
+
end
|
|
881
|
+
end
|
|
882
|
+
|
|
883
|
+
context "where name is blank" do
|
|
884
|
+
setup do
|
|
885
|
+
@s.name_is_blank = true
|
|
886
|
+
end
|
|
887
|
+
|
|
888
|
+
should "return 2 results" do
|
|
889
|
+
assert_equal 2, @s.all.size
|
|
890
|
+
end
|
|
891
|
+
|
|
892
|
+
should "contain no results with a present name column" do
|
|
893
|
+
assert_equal 0, @s.all.select {|r| r.name.present?}.size
|
|
894
|
+
end
|
|
895
|
+
end
|
|
896
|
+
|
|
897
|
+
context "where name is null" do
|
|
898
|
+
setup do
|
|
899
|
+
@s.name_is_null = true
|
|
900
|
+
end
|
|
901
|
+
|
|
902
|
+
should "return 1 result" do
|
|
903
|
+
assert_equal 1, @s.all.size
|
|
904
|
+
end
|
|
905
|
+
|
|
906
|
+
should "contain no results with a non-null name column" do
|
|
907
|
+
assert_equal 0, @s.all.select {|r| r.name != nil}.size
|
|
908
|
+
end
|
|
909
|
+
end
|
|
910
|
+
|
|
911
|
+
context "where name is not null" do
|
|
912
|
+
setup do
|
|
913
|
+
@s.name_is_not_null = true
|
|
914
|
+
end
|
|
915
|
+
|
|
916
|
+
should "return 6 results" do
|
|
917
|
+
assert_equal 6, @s.all.size
|
|
918
|
+
end
|
|
919
|
+
|
|
920
|
+
should "contain no results with a null name column" do
|
|
921
|
+
assert_equal 0, @s.all.select {|r| r.name = nil}.size
|
|
922
|
+
end
|
|
923
|
+
end
|
|
924
|
+
|
|
925
|
+
context "where notes_id is null" do
|
|
926
|
+
setup do
|
|
927
|
+
@s.notes_id_is_null = true
|
|
928
|
+
end
|
|
929
|
+
|
|
930
|
+
should "return 2 results" do
|
|
931
|
+
assert_equal 2, @s.all.size
|
|
932
|
+
end
|
|
933
|
+
|
|
934
|
+
should "contain no results with notes" do
|
|
935
|
+
assert_equal 0, @s.all.select {|r| r.notes.size > 0}.size
|
|
936
|
+
end
|
|
937
|
+
end
|
|
938
|
+
end
|
|
939
|
+
end
|
|
940
|
+
|
|
941
|
+
[{:name => 'Note', :object => Note},
|
|
942
|
+
{:name => 'Note as a Relation', :object => Note.scoped}].each do |object|
|
|
943
|
+
context_a_search_against object[:name], object[:object] do
|
|
944
|
+
should "allow search on polymorphic belongs_to associations" do
|
|
945
|
+
@s.notable_project_type_name_contains = 'MetaSearch'
|
|
946
|
+
assert_equal Project.find_by_name('MetaSearch Development').notes, @s.all
|
|
947
|
+
end
|
|
948
|
+
|
|
949
|
+
should "allow search on multiple polymorphic belongs_to associations" do
|
|
950
|
+
@s.notable_project_type_name_or_notable_developer_type_name_starts_with = 'M'
|
|
951
|
+
assert_equal Project.find_by_name('MetaSearch Development').notes +
|
|
952
|
+
Developer.find_by_name('Michael Bolton').notes,
|
|
953
|
+
@s.all
|
|
954
|
+
end
|
|
955
|
+
|
|
956
|
+
should "allow traversal of polymorphic associations" do
|
|
957
|
+
@s.notable_developer_type_company_name_starts_with = 'M'
|
|
958
|
+
assert_equal Company.find_by_name('Mission Data').developers.map(&:notes).flatten.sort {|a, b| a.id <=>b.id},
|
|
959
|
+
@s.all.sort {|a, b| a.id <=> b.id}
|
|
960
|
+
end
|
|
961
|
+
|
|
962
|
+
should "raise an error when attempting to search against polymorphic belongs_to association without a type" do
|
|
963
|
+
assert_raises ::MetaSearch::PolymorphicAssociationMissingTypeError do
|
|
964
|
+
@s.notable_name_contains = 'MetaSearch'
|
|
965
|
+
end
|
|
966
|
+
end
|
|
967
|
+
end
|
|
968
|
+
end
|
|
969
|
+
end
|