restful_query-rails3 0.4

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.
@@ -0,0 +1,35 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+ require 'shoulda'
4
+
5
+ $LOAD_PATH.unshift(File.join(File.expand_path(File.dirname(__FILE__)), '..'))
6
+ require 'lib/restful_query'
7
+
8
+
9
+ unless defined?(ActiveRecord)
10
+ module ActiveRecord
11
+ class Base
12
+ class << self
13
+ attr_accessor :pluralize_table_names
14
+
15
+ def protected_attributes
16
+ []
17
+ end
18
+
19
+ def named_scope(name, options = {})
20
+ end
21
+ end
22
+ self.pluralize_table_names = true
23
+
24
+ include RestfulQuery::CanQuery
25
+ end
26
+ end
27
+ end
28
+
29
+ class ClassWithQuery < ActiveRecord::Base
30
+ can_query
31
+ end
32
+
33
+ class ClassWithoutQuery < ActiveRecord::Base
34
+
35
+ end
@@ -0,0 +1,20 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestRestfulQueryCanQuery < Test::Unit::TestCase
4
+
5
+ context "CanQuery" do
6
+ context "A class with the can_query macro" do
7
+ should "can_query?" do
8
+ assert ClassWithQuery.can_query?
9
+ end
10
+ end
11
+
12
+ context "A class without the can_query macro" do
13
+ should "not can_query?" do
14
+ assert !ClassWithoutQuery.can_query?
15
+ end
16
+ end
17
+
18
+ end
19
+
20
+ end
@@ -0,0 +1,184 @@
1
+ require 'test_helper'
2
+
3
+ class RestfulQueryConditionTest < Test::Unit::TestCase
4
+
5
+ context "Condition" do
6
+
7
+ context "initializing" do
8
+ context "with column, value, operator" do
9
+ setup do
10
+ @condition = RestfulQuery::Condition.new('created_at', '1 week ago', '>')
11
+ end
12
+
13
+ should "save column" do
14
+ assert_equal 'created_at', @condition.column
15
+ end
16
+
17
+ should "save value" do
18
+ assert_equal '1 week ago', @condition.value
19
+ end
20
+
21
+ should "save operator as string" do
22
+ assert_equal '>', @condition.operator
23
+ end
24
+
25
+ end
26
+
27
+ context "with no operator" do
28
+ setup do
29
+ @condition = RestfulQuery::Condition.new('created_at', '1 week ago')
30
+ end
31
+
32
+ should "assume =" do
33
+ assert_equal '=', @condition.operator
34
+ end
35
+
36
+ end
37
+
38
+ context "with an operator as a string" do
39
+ setup do
40
+ @condition = RestfulQuery::Condition.new('created_at', '1 week ago', 'gteq')
41
+ end
42
+
43
+ should "translate string to operator" do
44
+ assert_equal '>=', @condition.operator
45
+ end
46
+
47
+ end
48
+
49
+ context "with chronic => true" do
50
+ setup do
51
+ @condition = RestfulQuery::Condition.new('created_at', '1 week ago', 'gteq', :chronic => true)
52
+ end
53
+
54
+ should "save option to options" do
55
+ assert @condition.options[:chronic]
56
+ end
57
+
58
+ should "parse value with chronic" do
59
+ assert_equal(Chronic.parse('1 week ago').to_s, @condition.value.to_s)
60
+ end
61
+ end
62
+
63
+ context "with a value of ':nil'" do
64
+ setup do
65
+ @condition = RestfulQuery::Condition.new('created_at', ':nil')
66
+ end
67
+
68
+ should "convert value to true nil" do
69
+ assert_equal(nil, @condition.value)
70
+ end
71
+ end
72
+
73
+ context "with a value of ':true'" do
74
+ setup do
75
+ @condition = RestfulQuery::Condition.new('created_at', ':true')
76
+ end
77
+
78
+ should "convert value to true true" do
79
+ assert_equal(true, @condition.value)
80
+ end
81
+ end
82
+
83
+ context "with a value of ':blank'" do
84
+ setup do
85
+ @condition = RestfulQuery::Condition.new('created_at', ':blank')
86
+ end
87
+
88
+ should "convert value to true true" do
89
+ assert_equal('', @condition.value)
90
+ end
91
+ end
92
+
93
+ context "with the IN operator" do
94
+ setup do
95
+ @condition = RestfulQuery::Condition.new('year', '1995,2005,2006', 'in')
96
+ end
97
+
98
+ should "assign the operator" do
99
+ assert_equal 'IN', @condition.operator
100
+ end
101
+
102
+ should "split values by the delimiter option" do
103
+ assert_equal ['1995', '2005', '2006'], @condition.value
104
+ end
105
+
106
+ should "include parens in placeholder" do
107
+ assert_equal ["year IN (?)", ['1995', '2005', '2006']], @condition.to_condition_array
108
+ end
109
+
110
+ context "when the value is already an array" do
111
+ setup do
112
+ @condition = RestfulQuery::Condition.new('year', ['1995', '2005', '2006'], 'in')
113
+ end
114
+
115
+ should "not resplit the value" do
116
+ assert_equal ['1995', '2005', '2006'], @condition.value
117
+ end
118
+ end
119
+ end
120
+
121
+ context "with the NOT IN operator" do
122
+ setup do
123
+ @condition = RestfulQuery::Condition.new('year', '1995|2005|2006', 'notin', :delimiter => '|')
124
+ end
125
+
126
+ should "assign the operator" do
127
+ assert_equal 'NOT IN', @condition.operator
128
+ end
129
+
130
+ should "split values by delimiter option" do
131
+ assert_equal ['1995', '2005', '2006'], @condition.value
132
+ end
133
+ end
134
+ end
135
+
136
+
137
+ context "a Condition" do
138
+ setup do
139
+ @condition = RestfulQuery::Condition.new('title', 'Bossman', 'lt')
140
+ end
141
+
142
+ context "with operator = like to condition array" do
143
+ setup do
144
+ @condition = RestfulQuery::Condition.new('title', 'Bossman', 'like')
145
+ @to_condition_array = @condition.to_condition_array
146
+ end
147
+
148
+ should "wrap value with %" do
149
+ assert_equal "%Bossman%", @to_condition_array[1]
150
+ end
151
+
152
+ should "translate operator to LIKE" do
153
+ assert_equal("title LIKE ?", @to_condition_array[0])
154
+ end
155
+
156
+ end
157
+
158
+ context "to_condition_array" do
159
+ setup do
160
+ @to_condition = @condition.to_condition_array
161
+ end
162
+
163
+ should "return array" do
164
+ assert @to_condition.is_a?(Array)
165
+ end
166
+
167
+ should "have conditional string first" do
168
+ assert_equal 'title < ?', @to_condition[0]
169
+ end
170
+
171
+ should "have value as [1]" do
172
+ assert_equal @condition.value, @to_condition[1]
173
+ end
174
+ end
175
+
176
+ context "to_hash" do
177
+ should "return hash like params" do
178
+ assert_equal({'title' => {'lt' => 'Bossman'}}, @condition.to_hash)
179
+ end
180
+ end
181
+ end
182
+ end
183
+
184
+ end
@@ -0,0 +1,467 @@
1
+ require 'test_helper'
2
+
3
+ class RestfulQueryParserTest < Test::Unit::TestCase
4
+
5
+ context "Parser" do
6
+ setup do
7
+ @base_query_hash = {'created_at' => {'gt' => '1 week ago', 'lt' => '1 hour ago'}, 'updated_at' => {'lt' => '1 day ago'}, 'title' => {'eq' => 'Test'}, 'other_time' => {'gt' => 'oct 1'}, 'name' => 'Aaron'}
8
+ end
9
+
10
+ context "from_hash" do
11
+
12
+ context "without hash" do
13
+ setup do
14
+ @parser = RestfulQuery::Parser.new(nil)
15
+ end
16
+
17
+ should "return Parser object" do
18
+ assert @parser.is_a?(RestfulQuery::Parser)
19
+ end
20
+
21
+ should "have a blank hash for query hash" do
22
+ assert_equal({}, @parser.to_query_hash)
23
+ end
24
+ end
25
+
26
+ context "with a hash of columns and operations" do
27
+ setup do
28
+ new_parser_from_hash
29
+ end
30
+
31
+ should "return parser object" do
32
+ assert @parser.is_a?(RestfulQuery::Parser)
33
+ end
34
+
35
+ should "save hash to query_hash" do
36
+ assert_equal @base_query_hash, @parser.to_query_hash
37
+ end
38
+
39
+ should "save each condition as a condition object" do
40
+ assert @parser.conditions.is_a?(Array)
41
+ assert @parser.conditions.first.is_a?(RestfulQuery::Condition)
42
+ end
43
+
44
+ should "save condition without operator with default operator" do
45
+ assert @parser.conditions_for(:name)
46
+ assert @parser.conditions_for(:name).first.is_a?(RestfulQuery::Condition)
47
+ assert_equal '=', @parser.conditions_for(:name).first.operator
48
+ end
49
+
50
+ end
51
+
52
+ context "with exclude columns" do
53
+ setup do
54
+ new_parser_from_hash({}, :exclude_columns => [:other_time,'name'])
55
+ end
56
+
57
+ should "return parser object" do
58
+ assert @parser.is_a?(RestfulQuery::Parser)
59
+ end
60
+
61
+ should "exclude columns from conditions" do
62
+ assert @parser.conditions_for('created_at')
63
+ assert_nil @parser.conditions_for('other_time')
64
+ assert_nil @parser.conditions_for(:name)
65
+ end
66
+
67
+ end
68
+
69
+ context "with chronic => true" do
70
+ setup do
71
+ new_parser_from_hash({}, :chronic => true)
72
+ end
73
+
74
+ should "return parser object" do
75
+ assert @parser.is_a?(RestfulQuery::Parser)
76
+ end
77
+
78
+ should "parse created at and updated with chronic" do
79
+ assert_equal Chronic.parse('1 week ago').to_s, @parser.conditions_for(:created_at).first.value.to_s
80
+ assert_equal Chronic.parse('1 day ago').to_s, @parser.conditions_for(:updated_at).first.value.to_s
81
+ end
82
+
83
+ end
84
+
85
+ context "with chronic => []" do
86
+ setup do
87
+ new_parser_from_hash({}, :chronic => [:other_time])
88
+ end
89
+
90
+ should "return parser object" do
91
+ assert @parser.is_a?(RestfulQuery::Parser)
92
+ end
93
+
94
+ should "parse selected attributes in array with chronic" do
95
+ assert_equal Chronic.parse('oct 1').to_s, @parser.conditions_for(:other_time).first.value.to_s
96
+ end
97
+
98
+ should "not parse created at/updated at if not specified" do
99
+ assert_not_equal Chronic.parse('1 week ago').to_s, @parser.conditions_for(:created_at).first.value.to_s
100
+ assert_not_equal Chronic.parse('1 day ago').to_s, @parser.conditions_for(:updated_at).first.value.to_s
101
+ end
102
+ end
103
+
104
+ context "with blank values" do
105
+ setup do
106
+ new_parser_from_hash({'isblank' => ''})
107
+ end
108
+
109
+ should "return parser object" do
110
+ assert @parser.is_a?(RestfulQuery::Parser)
111
+ end
112
+
113
+ should "not include conditions for blank values" do
114
+ assert @parser.conditions_for('created_at')
115
+ assert_nil @parser.conditions_for('isblank')
116
+ end
117
+ end
118
+
119
+ context "with map_columns" do
120
+ setup do
121
+ new_parser_from_hash({'section' => 4, '_sort' => 'category-up'}, {:map_columns => {
122
+ 'section' => 'section_id',
123
+ 'category' => 'category_id'
124
+ }})
125
+ end
126
+
127
+ should "return parser object" do
128
+ assert @parser.is_a?(RestfulQuery::Parser)
129
+ end
130
+
131
+ should "set the map_columns attribute" do
132
+ assert @parser.map_columns.is_a?(Hash)
133
+ end
134
+
135
+ should "map condition column" do
136
+ assert @parser.conditions_for('section')
137
+ assert_equal 'section_id', @parser.conditions_for('section').first.column
138
+ end
139
+
140
+ should "map sort column" do
141
+ @sort = @parser.sorts.first
142
+ assert @sort.is_a?(RestfulQuery::Sort)
143
+ assert_equal 'ASC', @sort.direction
144
+ assert_equal 'category_id', @sort.column
145
+ end
146
+ end
147
+
148
+ context "with sort as a single string" do
149
+ setup do
150
+ new_parser_from_hash({'_sort' => 'created_at-up'})
151
+ end
152
+
153
+ should "return parser object" do
154
+ assert @parser.is_a?(RestfulQuery::Parser)
155
+ end
156
+
157
+ should "parse sort string" do
158
+ @sort = @parser.sorts.first
159
+ assert @sort.is_a?(RestfulQuery::Sort)
160
+ assert_equal 'ASC', @sort.direction
161
+ assert_equal 'created_at', @sort.column
162
+ end
163
+
164
+ should "add sort to sorts" do
165
+ assert @parser.sorts
166
+ assert_equal 1, @parser.sorts.length
167
+ end
168
+
169
+ end
170
+
171
+ context "with sort as an array of strings" do
172
+ setup do
173
+ new_parser_from_hash({'_sort' => ['created_at-up','title-desc']})
174
+ end
175
+
176
+ should "return parser object" do
177
+ assert @parser.is_a?(RestfulQuery::Parser)
178
+ end
179
+
180
+ should "add sorts to sorts" do
181
+ assert @parser.sorts
182
+ assert_equal 2, @parser.sorts.length
183
+ @parser.sorts.each do |sort|
184
+ assert sort.is_a?(RestfulQuery::Sort)
185
+ end
186
+ end
187
+
188
+ end
189
+
190
+ context "with a default_sort" do
191
+ context "with no sorts defined in the query hash" do
192
+ setup do
193
+ new_parser_from_hash({}, {:default_sort => 'created_at DESC'})
194
+ end
195
+
196
+ should "return parser object" do
197
+ assert @parser.is_a?(RestfulQuery::Parser)
198
+ end
199
+
200
+ should "have default sort in sorts" do
201
+ assert @parser.sorts
202
+ assert_equal 1, @parser.sorts.length
203
+ assert_equal 'created_at DESC', @parser.sort_sql
204
+ end
205
+ end
206
+
207
+ context "with sorts defined in the query hash" do
208
+ setup do
209
+ new_parser_from_hash({'_sort' => 'created_at-up'})
210
+ end
211
+
212
+ should "return parser object" do
213
+ assert @parser.is_a?(RestfulQuery::Parser)
214
+ end
215
+
216
+ should "have query hash sorts in sorts and not default sort" do
217
+ assert @parser.sorts
218
+ assert_equal 1, @parser.sorts.length
219
+ assert_equal 'created_at ASC', @parser.sort_sql
220
+ end
221
+ end
222
+ end
223
+ end
224
+
225
+ context "from an array of conditions" do
226
+ setup do
227
+ @array_of_conditions = [
228
+ {'column' => 'created_at', 'operator' => 'gt', 'value' => '1 week ago'},
229
+ {'column' => 'created_at', 'operator' => 'lt', 'value' => '1 hour ago'},
230
+ {'column' => 'updated_at', 'operator' => 'lt', 'value' => '1 day ago'},
231
+ {'column' => 'title', 'operator' => 'eq', 'value' => 'Test'},
232
+ {'column' => 'other_time', 'operator' => 'gt', 'value' => 'oct 1'},
233
+ {'column' => 'name', 'value' => 'Aaron'}
234
+ ]
235
+ @parser = RestfulQuery::Parser.new(:conditions => @array_of_conditions)
236
+ end
237
+
238
+ should "return parser object" do
239
+ assert @parser.is_a?(RestfulQuery::Parser)
240
+ end
241
+
242
+ should "save each condition as a condition object" do
243
+ assert @parser.conditions.is_a?(Array)
244
+ assert_equal 6, @parser.conditions.length
245
+ assert @parser.conditions.first.is_a?(RestfulQuery::Condition)
246
+ end
247
+
248
+ should "save condition without operator with default operator" do
249
+ assert @parser.conditions_for(:name)
250
+ assert @parser.conditions_for(:name).first.is_a?(RestfulQuery::Condition)
251
+ assert_equal '=', @parser.conditions_for(:name).first.operator
252
+ end
253
+
254
+ end
255
+
256
+ context "a loaded parser" do
257
+ setup do
258
+ new_parser_from_hash
259
+ end
260
+
261
+ context "conditions" do
262
+ setup do
263
+ @conditions = @parser.conditions
264
+ end
265
+
266
+ should "return array of all conditions objects" do
267
+ assert @conditions.is_a?(Array)
268
+ @conditions.each do |condition|
269
+ assert condition.is_a?(RestfulQuery::Condition)
270
+ end
271
+ end
272
+
273
+ should "include conditions for every attribute" do
274
+ assert_equal @base_query_hash.keys.length + 1, @conditions.length
275
+ end
276
+ end
277
+
278
+ context "conditions_for" do
279
+ should "return nil for columns without conditions" do
280
+ assert_nil @parser.conditions_for(:blah)
281
+ end
282
+
283
+ should "return array of conditions for column that exists" do
284
+ @conditions = @parser.conditions_for(:created_at)
285
+ assert @conditions.is_a?(Array)
286
+ @conditions.each do |condition|
287
+ assert condition.is_a?(RestfulQuery::Condition)
288
+ assert_equal 'created_at', condition.column
289
+ end
290
+ end
291
+
292
+ end
293
+
294
+ context "to conditions array" do
295
+ setup do
296
+ @conditions = @parser.to_conditions_array
297
+ end
298
+
299
+ should "return array" do
300
+ assert @conditions.is_a?(Array)
301
+ end
302
+
303
+ should "first element should be a condition string" do
304
+ assert @conditions[0].is_a?(String)
305
+ end
306
+
307
+ should "include operators for all querys" do
308
+ assert_match(/(([a-z_]) (\<|\>|\=|\<\=|\>\=) \? AND)+/,@conditions[0])
309
+ end
310
+
311
+ should "join query hash with AND" do
312
+ assert_match(/AND/,@conditions[0])
313
+ end
314
+
315
+ should "include values for each conditions" do
316
+ assert_equal @base_query_hash.keys.length + 2, @conditions.length
317
+ end
318
+
319
+ end
320
+
321
+ context "to conditions with :or" do
322
+ setup do
323
+ @conditions = @parser.to_conditions_array(:or)
324
+ end
325
+
326
+ should "join query hash with OR" do
327
+ assert_match(/(([a-z_]) (\<|\>|\=|\<\=|\>\=) \? OR)+/,@conditions[0])
328
+ end
329
+ end
330
+
331
+ context "to_query_hash" do
332
+ context "with no altering" do
333
+ setup do
334
+ @query_hash = @parser.to_query_hash
335
+ end
336
+
337
+ should "return hash" do
338
+ assert @query_hash.is_a?(Hash)
339
+ end
340
+
341
+ should "return initial query hash" do
342
+ assert_equal({'gt' => '1 week ago', 'lt' => '1 hour ago'}, @query_hash['created_at'])
343
+ end
344
+ end
345
+
346
+ context "with altered sorts" do
347
+ setup do
348
+ @parser.set_sort('title', 'up')
349
+ @parser.set_sort('created_at', 'down')
350
+ @query_hash = @parser.to_query_hash
351
+ end
352
+
353
+ should "include unaltered sort conditions" do
354
+ assert_equal({'gt' => '1 week ago', 'lt' => '1 hour ago'}, @query_hash['created_at'])
355
+ end
356
+
357
+ should "include altered sorts" do
358
+ assert_equal(['title-asc','created_at-desc'], @query_hash['_sort'])
359
+ end
360
+ end
361
+ end
362
+
363
+ context "sorts" do
364
+ setup do
365
+ new_parser_from_hash({'_sort' => ['title-down', 'updated_at-asc']})
366
+ @sorts = @parser.sorts
367
+ end
368
+
369
+ should "return an array of sort objects" do
370
+ assert @sorts
371
+ assert_equal 2, @sorts.length
372
+ @sorts.each do |sort|
373
+ assert sort.is_a?(RestfulQuery::Sort)
374
+ end
375
+ end
376
+
377
+ context "sorted_columns" do
378
+ should "return an array of columns" do
379
+ @sorted_columns = @parser.sorted_columns
380
+ assert @sorted_columns.is_a?(Array)
381
+ assert @sorted_columns.include?('title')
382
+ end
383
+ end
384
+
385
+ context "sorted_by?" do
386
+ should "return true if column is sorted" do
387
+ assert @parser.sorted_by?('title')
388
+ end
389
+
390
+ should "return false if column is not sorted" do
391
+ assert !@parser.sorted_by?('created_at')
392
+ end
393
+ end
394
+
395
+ context "sort()" do
396
+ should "return Sort object if column is sorted" do
397
+ sort = @parser.sort('title')
398
+ assert sort.is_a?(RestfulQuery::Sort)
399
+ assert_equal 'title', sort.column
400
+ end
401
+
402
+ should "return nil if col" do
403
+ assert_nil @parser.sort('created_at')
404
+ end
405
+ end
406
+
407
+ context "set_sort" do
408
+ context "with an existing sort" do
409
+ setup do
410
+ @parser.set_sort('title','up')
411
+ end
412
+
413
+ should "not add new sort" do
414
+ assert_equal 2, @parser.sorts.length
415
+ end
416
+
417
+ should "update sort direction" do
418
+ assert_equal 'ASC', @parser.sort('title').direction
419
+ end
420
+ end
421
+
422
+ context "with direction: nil" do
423
+ setup do
424
+ @parser.set_sort('title', nil)
425
+ end
426
+
427
+ should "remove sort" do
428
+ assert_equal 1, @parser.sorts.length
429
+ assert !@parser.sorted_by?('title')
430
+ end
431
+ end
432
+
433
+ context "with a new sort" do
434
+ setup do
435
+ @parser.set_sort('name', 'down')
436
+ end
437
+
438
+ should "add sort to sorts" do
439
+ assert_equal 3, @parser.sorts.length
440
+ end
441
+
442
+ should "set sort direction" do
443
+ assert_equal 'DESC', @parser.sort('name').direction
444
+ end
445
+ end
446
+
447
+ end
448
+
449
+ end
450
+
451
+
452
+ context "sort_sql" do
453
+ should "join order with ," do
454
+ new_parser_from_hash({'_sort' => ['title-down', 'updated_at-asc']})
455
+ assert_equal 'title DESC, updated_at ASC', @parser.sort_sql
456
+ end
457
+ end
458
+
459
+ end
460
+
461
+ end
462
+
463
+ protected
464
+ def new_parser_from_hash(params = {}, options = {})
465
+ @parser = RestfulQuery::Parser.new(@base_query_hash.merge(params), options)
466
+ end
467
+ end