restful_query 0.3.3 → 0.3.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.
- data/History.txt +6 -0
- data/lib/restful_query.rb +1 -1
- data/lib/restful_query/parser.rb +25 -23
- data/lib/restful_query/sort.rb +41 -21
- data/restful_query.gemspec +3 -4
- data/test/test_restful_query_parser.rb +61 -46
- data/test/test_restful_query_sort.rb +40 -13
- metadata +45 -70
data/History.txt
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
== 0.3.4 2011-08-15
|
2
|
+
|
3
|
+
* Added support for extra options to sort. Specifically this allows you to do NULLS FIRST/LAST
|
4
|
+
* You can supply :sort_options => to the restful query parser that will get added to all sorts
|
5
|
+
* Changed single_sort => true to the default
|
6
|
+
|
1
7
|
== 0.3.3 2011-05-15
|
2
8
|
|
3
9
|
* Added 'restful_query/rails' for bundler requires
|
data/lib/restful_query.rb
CHANGED
data/lib/restful_query/parser.rb
CHANGED
@@ -1,15 +1,16 @@
|
|
1
1
|
module RestfulQuery
|
2
2
|
class Parser
|
3
|
-
attr_reader :query, :exclude_columns, :map_columns, :integer_columns, :options
|
3
|
+
attr_reader :query, :exclude_columns, :map_columns, :integer_columns, :options, :default_sort_options
|
4
4
|
|
5
5
|
def initialize(query, options = {})
|
6
6
|
@options = options || {}
|
7
7
|
@exclude_columns = columns_from_options(:exclude, options)
|
8
8
|
@integer_columns = columns_from_options(:integer, options)
|
9
9
|
@map_columns = options[:map_columns] || {}
|
10
|
-
@
|
11
|
-
@
|
10
|
+
@single_sort = options[:single_sort] || true
|
11
|
+
@default_sort_options = options[:sort_options] || {}
|
12
12
|
@query = (query || {}).dup
|
13
|
+
@query['_sort'] ||= options[:default_sort] if options[:default_sort]
|
13
14
|
@default_join = @query.delete(:join) || :and
|
14
15
|
extract_sorts_from_conditions
|
15
16
|
map_conditions
|
@@ -18,7 +19,7 @@ module RestfulQuery
|
|
18
19
|
def conditions
|
19
20
|
conditions_hash.values.flatten
|
20
21
|
end
|
21
|
-
|
22
|
+
|
22
23
|
def has_conditions?
|
23
24
|
!conditions.empty?
|
24
25
|
end
|
@@ -32,46 +33,46 @@ module RestfulQuery
|
|
32
33
|
join_string = (join == :or) ? ' OR ' : ' AND '
|
33
34
|
conditions_string = []
|
34
35
|
conditions_values = []
|
35
|
-
conditions.each do |c|
|
36
|
+
conditions.each do |c|
|
36
37
|
ca = c.to_condition_array
|
37
38
|
conditions_string << ca[0]
|
38
39
|
conditions_values << ca[1]
|
39
40
|
end
|
40
41
|
conditions_values.unshift(conditions_string.join(join_string))
|
41
42
|
end
|
42
|
-
|
43
|
+
|
43
44
|
def to_query_hash
|
44
45
|
hash = @query
|
45
46
|
hash['_sort'] = sorts.collect {|s| s.to_s } unless sorts.empty?
|
46
47
|
hash
|
47
48
|
end
|
48
|
-
|
49
|
+
|
49
50
|
def sort_sql
|
50
51
|
@sorts.collect {|s| s.to_sql }.join(', ')
|
51
52
|
end
|
52
|
-
|
53
|
+
|
53
54
|
def has_sort?
|
54
55
|
!sorts.empty?
|
55
56
|
end
|
56
|
-
|
57
|
+
|
57
58
|
def sorts
|
58
59
|
@sorts ||= []
|
59
60
|
end
|
60
|
-
|
61
|
+
|
61
62
|
def sorted_columns
|
62
63
|
sorts.collect {|s| s.column }
|
63
64
|
end
|
64
|
-
|
65
|
+
|
65
66
|
def sorted_by?(column_name)
|
66
67
|
column = map_column(column_name)
|
67
68
|
sorted_columns.include?(column.to_s)
|
68
69
|
end
|
69
|
-
|
70
|
+
|
70
71
|
def sort(column_name)
|
71
72
|
column = map_column(column_name)
|
72
73
|
sorts.detect {|s| s && s.column == column }
|
73
74
|
end
|
74
|
-
|
75
|
+
|
75
76
|
def set_sort(column_name, direction)
|
76
77
|
column = map_column(column_name)
|
77
78
|
if new_sort = self.sort(column_name)
|
@@ -86,7 +87,7 @@ module RestfulQuery
|
|
86
87
|
end
|
87
88
|
new_sort
|
88
89
|
end
|
89
|
-
|
90
|
+
|
90
91
|
def clear_default_sort!
|
91
92
|
@sorts.reject! {|s| s == @default_sort.first }
|
92
93
|
end
|
@@ -108,7 +109,7 @@ module RestfulQuery
|
|
108
109
|
[]
|
109
110
|
end
|
110
111
|
end
|
111
|
-
|
112
|
+
|
112
113
|
def extract_sorts_from_conditions
|
113
114
|
@sorts = sorts_from_hash(@query.delete('_sort'))
|
114
115
|
@sorts = @default_sort if @sorts.empty?
|
@@ -142,25 +143,26 @@ module RestfulQuery
|
|
142
143
|
end
|
143
144
|
end
|
144
145
|
end
|
145
|
-
|
146
|
+
|
146
147
|
def sorts_from_hash(sorts)
|
147
148
|
sort_conditions = [sorts].flatten.compact
|
148
|
-
sort_conditions.collect do |c|
|
149
|
+
sort_conditions.collect do |c|
|
149
150
|
s = Sort.parse(c)
|
150
151
|
s.column = map_column(s.column)
|
152
|
+
s.options = default_sort_options
|
151
153
|
s
|
152
154
|
end
|
153
|
-
end
|
154
|
-
|
155
|
+
end
|
156
|
+
|
155
157
|
def columns_from_options(column_type, options)
|
156
158
|
option = "#{column_type}_columns".to_sym
|
157
159
|
options[option] ? [options.delete(option)].flatten.collect {|c| c.to_s } : []
|
158
160
|
end
|
159
|
-
|
161
|
+
|
160
162
|
def map_column(column_name)
|
161
163
|
map_columns[column_name.to_s] || column_name.to_s
|
162
164
|
end
|
163
|
-
|
164
|
-
|
165
|
+
|
166
|
+
|
165
167
|
end
|
166
|
-
end
|
168
|
+
end
|
data/lib/restful_query/sort.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
module RestfulQuery
|
2
2
|
class InvalidDirection < Error; end
|
3
|
-
|
3
|
+
|
4
4
|
class Sort
|
5
5
|
include Comparable
|
6
|
-
|
7
|
-
attr_reader :column, :direction
|
8
|
-
|
6
|
+
|
7
|
+
attr_reader :column, :direction, :options
|
8
|
+
|
9
9
|
DIRECTIONS = {
|
10
10
|
'up' => 'ASC',
|
11
11
|
'asc' => 'ASC',
|
@@ -14,37 +14,51 @@ module RestfulQuery
|
|
14
14
|
'desc' => 'DESC',
|
15
15
|
'DESC' => 'DESC'
|
16
16
|
}.freeze
|
17
|
-
|
18
|
-
|
19
|
-
def initialize(column, direction)
|
17
|
+
|
18
|
+
|
19
|
+
def initialize(column, direction, options = {})
|
20
20
|
self.column = column
|
21
21
|
self.direction = direction
|
22
|
+
self.options = options
|
22
23
|
end
|
23
|
-
|
24
|
+
|
24
25
|
def self.parse(sort_string, split_on = /\-|\ /)
|
25
26
|
return unless sort_string
|
26
|
-
column, direction = sort_string.split(split_on)
|
27
|
-
new(column, direction)
|
27
|
+
column, direction, options = sort_string.split(split_on, 3)
|
28
|
+
new(column, direction, options)
|
28
29
|
end
|
29
|
-
|
30
|
+
|
30
31
|
def column=(column)
|
31
32
|
@column = column.to_s
|
32
33
|
end
|
33
|
-
|
34
|
+
|
34
35
|
def direction=(direction)
|
35
36
|
@direction = DIRECTIONS[direction.to_s]
|
36
37
|
raise(InvalidDirection, "'#{direction}' is not a valid order direction") unless @direction
|
37
38
|
end
|
38
|
-
|
39
|
+
|
40
|
+
def options=(options)
|
41
|
+
@options = if options.is_a?(String)
|
42
|
+
opts = {}
|
43
|
+
options.split(/ /).each_slice(2) do |k|
|
44
|
+
k.map! {|v| v.to_s.downcase.to_sym }
|
45
|
+
opts[k[0]] = k[1]
|
46
|
+
end
|
47
|
+
opts
|
48
|
+
else
|
49
|
+
options || {}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
39
53
|
def reverse_direction
|
40
54
|
direction == 'ASC' ? 'DESC' : 'ASC'
|
41
55
|
end
|
42
|
-
|
56
|
+
|
43
57
|
def ==(other)
|
44
58
|
return false unless other.is_a?(Sort)
|
45
59
|
column == other.column && direction == other.direction
|
46
60
|
end
|
47
|
-
|
61
|
+
|
48
62
|
# Makes a roundabout for directions nil -> desc -> asc -> nil
|
49
63
|
def self.next_direction(current_direction)
|
50
64
|
case current_direction.to_s.downcase
|
@@ -56,17 +70,23 @@ module RestfulQuery
|
|
56
70
|
'desc'
|
57
71
|
end
|
58
72
|
end
|
59
|
-
|
73
|
+
|
60
74
|
def next_direction
|
61
75
|
self.class.next_direction(direction)
|
62
76
|
end
|
63
|
-
|
77
|
+
|
64
78
|
def to_s(join = '-')
|
65
|
-
"#{column}#{join}#{direction.downcase}"
|
79
|
+
s = "#{column}#{join}#{direction.downcase}"
|
80
|
+
s << " #{options.inspect}" unless options.empty?
|
81
|
+
s
|
66
82
|
end
|
67
|
-
|
83
|
+
|
68
84
|
def to_sql
|
69
|
-
"#{column} #{direction}"
|
85
|
+
sql = "#{column} #{direction}"
|
86
|
+
unless options.empty?
|
87
|
+
sql << ' ' << options.to_a.flatten.collect {|k| k.to_s.upcase }.join(' ')
|
88
|
+
end
|
89
|
+
sql
|
70
90
|
end
|
71
91
|
end
|
72
|
-
end
|
92
|
+
end
|
data/restful_query.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{restful_query}
|
8
|
-
s.version = "0.3.
|
8
|
+
s.version = "0.3.4"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Aaron Quint"]
|
12
|
-
s.date = %q{2011-
|
12
|
+
s.date = %q{2011-08-15}
|
13
13
|
s.description = %q{RestfulQuery provides a simple interface in front of a complex parser to parse specially formatted query hashes into complex SQL queries. It includes ActiveRecord and Sequel extensions.}
|
14
14
|
s.extra_rdoc_files = [
|
15
15
|
"LICENSE",
|
@@ -39,11 +39,10 @@ Gem::Specification.new do |s|
|
|
39
39
|
]
|
40
40
|
s.require_paths = ["lib"]
|
41
41
|
s.rubyforge_project = %q{quirkey}
|
42
|
-
s.rubygems_version = %q{1.
|
42
|
+
s.rubygems_version = %q{1.6.2}
|
43
43
|
s.summary = %q{Simple ActiveRecord and Sequel queries from a RESTful and safe interface}
|
44
44
|
|
45
45
|
if s.respond_to? :specification_version then
|
46
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
47
46
|
s.specification_version = 3
|
48
47
|
|
49
48
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
@@ -100,7 +100,7 @@ class RestfulQueryParserTest < Test::Unit::TestCase
|
|
100
100
|
assert_not_equal Chronic.parse('1 day ago').to_s, @parser.conditions_for(:updated_at).first.value.to_s
|
101
101
|
end
|
102
102
|
end
|
103
|
-
|
103
|
+
|
104
104
|
context "with blank values" do
|
105
105
|
setup do
|
106
106
|
new_parser_from_hash({'isblank' => ''})
|
@@ -115,7 +115,7 @@ class RestfulQueryParserTest < Test::Unit::TestCase
|
|
115
115
|
assert_nil @parser.conditions_for('isblank')
|
116
116
|
end
|
117
117
|
end
|
118
|
-
|
118
|
+
|
119
119
|
context "with map_columns" do
|
120
120
|
setup do
|
121
121
|
new_parser_from_hash({'section' => 4, '_sort' => 'category-up'}, {:map_columns => {
|
@@ -123,22 +123,22 @@ class RestfulQueryParserTest < Test::Unit::TestCase
|
|
123
123
|
'category' => 'category_id'
|
124
124
|
}})
|
125
125
|
end
|
126
|
-
|
126
|
+
|
127
127
|
should "return parser object" do
|
128
128
|
assert @parser.is_a?(RestfulQuery::Parser)
|
129
129
|
end
|
130
|
-
|
130
|
+
|
131
131
|
should "set the map_columns attribute" do
|
132
132
|
assert @parser.map_columns.is_a?(Hash)
|
133
133
|
end
|
134
|
-
|
134
|
+
|
135
135
|
should "map condition column" do
|
136
136
|
assert @parser.conditions_for('section')
|
137
137
|
assert_equal 'section_id', @parser.conditions_for('section').first.column
|
138
138
|
end
|
139
|
-
|
139
|
+
|
140
140
|
should "map sort column" do
|
141
|
-
@sort = @parser.sorts.first
|
141
|
+
@sort = @parser.sorts.first
|
142
142
|
assert @sort.is_a?(RestfulQuery::Sort)
|
143
143
|
assert_equal 'ASC', @sort.direction
|
144
144
|
assert_equal 'category_id', @sort.column
|
@@ -155,7 +155,7 @@ class RestfulQueryParserTest < Test::Unit::TestCase
|
|
155
155
|
end
|
156
156
|
|
157
157
|
should "parse sort string" do
|
158
|
-
@sort = @parser.sorts.first
|
158
|
+
@sort = @parser.sorts.first
|
159
159
|
assert @sort.is_a?(RestfulQuery::Sort)
|
160
160
|
assert_equal 'ASC', @sort.direction
|
161
161
|
assert_equal 'created_at', @sort.column
|
@@ -184,26 +184,41 @@ class RestfulQueryParserTest < Test::Unit::TestCase
|
|
184
184
|
assert sort.is_a?(RestfulQuery::Sort)
|
185
185
|
end
|
186
186
|
end
|
187
|
+
end
|
187
188
|
|
189
|
+
context "with sort options" do
|
190
|
+
setup do
|
191
|
+
new_parser_from_hash({'_sort' => ['created_at-up']}, :sort_options => {:nulls => :first})
|
192
|
+
end
|
193
|
+
|
194
|
+
should "return parser object" do
|
195
|
+
assert @parser.is_a?(RestfulQuery::Parser)
|
196
|
+
end
|
197
|
+
|
198
|
+
should "add sorts to sorts" do
|
199
|
+
assert @parser.sorts
|
200
|
+
assert_equal 1, @parser.sorts.length
|
201
|
+
assert_equal 'created_at ASC NULLS FIRST', @parser.sort_sql
|
202
|
+
end
|
188
203
|
end
|
189
|
-
|
204
|
+
|
190
205
|
context "with a default_sort" do
|
191
206
|
context "with no sorts defined in the query hash" do
|
192
207
|
setup do
|
193
208
|
new_parser_from_hash({}, {:default_sort => 'created_at DESC'})
|
194
209
|
end
|
195
|
-
|
210
|
+
|
196
211
|
should "return parser object" do
|
197
212
|
assert @parser.is_a?(RestfulQuery::Parser)
|
198
213
|
end
|
199
|
-
|
214
|
+
|
200
215
|
should "have default sort in sorts" do
|
201
216
|
assert @parser.sorts
|
202
217
|
assert_equal 1, @parser.sorts.length
|
203
218
|
assert_equal 'created_at DESC', @parser.sort_sql
|
204
219
|
end
|
205
220
|
end
|
206
|
-
|
221
|
+
|
207
222
|
context "with sorts defined in the query hash" do
|
208
223
|
setup do
|
209
224
|
new_parser_from_hash({'_sort' => 'created_at-up'})
|
@@ -212,7 +227,7 @@ class RestfulQueryParserTest < Test::Unit::TestCase
|
|
212
227
|
should "return parser object" do
|
213
228
|
assert @parser.is_a?(RestfulQuery::Parser)
|
214
229
|
end
|
215
|
-
|
230
|
+
|
216
231
|
should "have query hash sorts in sorts and not default sort" do
|
217
232
|
assert @parser.sorts
|
218
233
|
assert_equal 1, @parser.sorts.length
|
@@ -221,20 +236,20 @@ class RestfulQueryParserTest < Test::Unit::TestCase
|
|
221
236
|
end
|
222
237
|
end
|
223
238
|
end
|
224
|
-
|
239
|
+
|
225
240
|
context "from an array of conditions" do
|
226
241
|
setup do
|
227
242
|
@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'},
|
243
|
+
{'column' => 'created_at', 'operator' => 'gt', 'value' => '1 week ago'},
|
244
|
+
{'column' => 'created_at', 'operator' => 'lt', 'value' => '1 hour ago'},
|
245
|
+
{'column' => 'updated_at', 'operator' => 'lt', 'value' => '1 day ago'},
|
246
|
+
{'column' => 'title', 'operator' => 'eq', 'value' => 'Test'},
|
232
247
|
{'column' => 'other_time', 'operator' => 'gt', 'value' => 'oct 1'},
|
233
248
|
{'column' => 'name', 'value' => 'Aaron'}
|
234
249
|
]
|
235
250
|
@parser = RestfulQuery::Parser.new(:conditions => @array_of_conditions)
|
236
251
|
end
|
237
|
-
|
252
|
+
|
238
253
|
should "return parser object" do
|
239
254
|
assert @parser.is_a?(RestfulQuery::Parser)
|
240
255
|
end
|
@@ -250,7 +265,7 @@ class RestfulQueryParserTest < Test::Unit::TestCase
|
|
250
265
|
assert @parser.conditions_for(:name).first.is_a?(RestfulQuery::Condition)
|
251
266
|
assert_equal '=', @parser.conditions_for(:name).first.operator
|
252
267
|
end
|
253
|
-
|
268
|
+
|
254
269
|
end
|
255
270
|
|
256
271
|
context "a loaded parser" do
|
@@ -327,45 +342,45 @@ class RestfulQueryParserTest < Test::Unit::TestCase
|
|
327
342
|
assert_match(/(([a-z_]) (\<|\>|\=|\<\=|\>\=) \? OR)+/,@conditions[0])
|
328
343
|
end
|
329
344
|
end
|
330
|
-
|
345
|
+
|
331
346
|
context "to_query_hash" do
|
332
347
|
context "with no altering" do
|
333
348
|
setup do
|
334
349
|
@query_hash = @parser.to_query_hash
|
335
350
|
end
|
336
|
-
|
351
|
+
|
337
352
|
should "return hash" do
|
338
353
|
assert @query_hash.is_a?(Hash)
|
339
354
|
end
|
340
|
-
|
355
|
+
|
341
356
|
should "return initial query hash" do
|
342
357
|
assert_equal({'gt' => '1 week ago', 'lt' => '1 hour ago'}, @query_hash['created_at'])
|
343
358
|
end
|
344
359
|
end
|
345
|
-
|
360
|
+
|
346
361
|
context "with altered sorts" do
|
347
362
|
setup do
|
348
363
|
@parser.set_sort('title', 'up')
|
349
364
|
@parser.set_sort('created_at', 'down')
|
350
365
|
@query_hash = @parser.to_query_hash
|
351
366
|
end
|
352
|
-
|
367
|
+
|
353
368
|
should "include unaltered sort conditions" do
|
354
369
|
assert_equal({'gt' => '1 week ago', 'lt' => '1 hour ago'}, @query_hash['created_at'])
|
355
370
|
end
|
356
|
-
|
371
|
+
|
357
372
|
should "include altered sorts" do
|
358
373
|
assert_equal(['title-asc','created_at-desc'], @query_hash['_sort'])
|
359
374
|
end
|
360
375
|
end
|
361
376
|
end
|
362
|
-
|
377
|
+
|
363
378
|
context "sorts" do
|
364
379
|
setup do
|
365
380
|
new_parser_from_hash({'_sort' => ['title-down', 'updated_at-asc']})
|
366
|
-
@sorts = @parser.sorts
|
381
|
+
@sorts = @parser.sorts
|
367
382
|
end
|
368
|
-
|
383
|
+
|
369
384
|
should "return an array of sort objects" do
|
370
385
|
assert @sorts
|
371
386
|
assert_equal 2, @sorts.length
|
@@ -373,7 +388,7 @@ class RestfulQueryParserTest < Test::Unit::TestCase
|
|
373
388
|
assert sort.is_a?(RestfulQuery::Sort)
|
374
389
|
end
|
375
390
|
end
|
376
|
-
|
391
|
+
|
377
392
|
context "sorted_columns" do
|
378
393
|
should "return an array of columns" do
|
379
394
|
@sorted_columns = @parser.sorted_columns
|
@@ -381,73 +396,73 @@ class RestfulQueryParserTest < Test::Unit::TestCase
|
|
381
396
|
assert @sorted_columns.include?('title')
|
382
397
|
end
|
383
398
|
end
|
384
|
-
|
399
|
+
|
385
400
|
context "sorted_by?" do
|
386
401
|
should "return true if column is sorted" do
|
387
402
|
assert @parser.sorted_by?('title')
|
388
403
|
end
|
389
|
-
|
404
|
+
|
390
405
|
should "return false if column is not sorted" do
|
391
406
|
assert !@parser.sorted_by?('created_at')
|
392
407
|
end
|
393
408
|
end
|
394
|
-
|
409
|
+
|
395
410
|
context "sort()" do
|
396
411
|
should "return Sort object if column is sorted" do
|
397
412
|
sort = @parser.sort('title')
|
398
413
|
assert sort.is_a?(RestfulQuery::Sort)
|
399
414
|
assert_equal 'title', sort.column
|
400
415
|
end
|
401
|
-
|
416
|
+
|
402
417
|
should "return nil if col" do
|
403
418
|
assert_nil @parser.sort('created_at')
|
404
419
|
end
|
405
420
|
end
|
406
|
-
|
421
|
+
|
407
422
|
context "set_sort" do
|
408
|
-
context "with an existing sort" do
|
423
|
+
context "with an existing sort" do
|
409
424
|
setup do
|
410
425
|
@parser.set_sort('title','up')
|
411
426
|
end
|
412
|
-
|
427
|
+
|
413
428
|
should "not add new sort" do
|
414
429
|
assert_equal 2, @parser.sorts.length
|
415
430
|
end
|
416
|
-
|
431
|
+
|
417
432
|
should "update sort direction" do
|
418
433
|
assert_equal 'ASC', @parser.sort('title').direction
|
419
434
|
end
|
420
435
|
end
|
421
|
-
|
436
|
+
|
422
437
|
context "with direction: nil" do
|
423
438
|
setup do
|
424
439
|
@parser.set_sort('title', nil)
|
425
440
|
end
|
426
|
-
|
441
|
+
|
427
442
|
should "remove sort" do
|
428
443
|
assert_equal 1, @parser.sorts.length
|
429
444
|
assert !@parser.sorted_by?('title')
|
430
445
|
end
|
431
446
|
end
|
432
|
-
|
447
|
+
|
433
448
|
context "with a new sort" do
|
434
449
|
setup do
|
435
450
|
@parser.set_sort('name', 'down')
|
436
451
|
end
|
437
|
-
|
452
|
+
|
438
453
|
should "add sort to sorts" do
|
439
454
|
assert_equal 3, @parser.sorts.length
|
440
455
|
end
|
441
|
-
|
456
|
+
|
442
457
|
should "set sort direction" do
|
443
458
|
assert_equal 'DESC', @parser.sort('name').direction
|
444
459
|
end
|
445
460
|
end
|
446
|
-
|
461
|
+
|
447
462
|
end
|
448
|
-
|
463
|
+
|
449
464
|
end
|
450
|
-
|
465
|
+
|
451
466
|
|
452
467
|
context "sort_sql" do
|
453
468
|
should "join order with ," do
|
@@ -8,16 +8,34 @@ class RestfulQuerySortTest < Test::Unit::TestCase
|
|
8
8
|
setup do
|
9
9
|
@sort = RestfulQuery::Sort.new(:attribute, 'up')
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
should "save column name as string" do
|
13
13
|
assert_equal 'attribute', @sort.column
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
should "interpret direction" do
|
17
17
|
assert_equal 'ASC', @sort.direction
|
18
18
|
end
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
|
+
context "with extra options" do
|
22
|
+
setup do
|
23
|
+
@sort = RestfulQuery::Sort.new(:attribute, 'up', :nulls => :first)
|
24
|
+
end
|
25
|
+
|
26
|
+
should "save column name as string" do
|
27
|
+
assert_equal 'attribute', @sort.column
|
28
|
+
end
|
29
|
+
|
30
|
+
should "interpret direction" do
|
31
|
+
assert_equal 'ASC', @sort.direction
|
32
|
+
end
|
33
|
+
|
34
|
+
should "add nulls option" do
|
35
|
+
assert_equal :first, @sort.options[:nulls]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
21
39
|
context "with an invalid direction" do
|
22
40
|
should "raise error" do
|
23
41
|
assert_raise(RestfulQuery::InvalidDirection) do
|
@@ -25,28 +43,28 @@ class RestfulQuerySortTest < Test::Unit::TestCase
|
|
25
43
|
end
|
26
44
|
end
|
27
45
|
end
|
28
|
-
|
46
|
+
|
29
47
|
end
|
30
|
-
|
48
|
+
|
31
49
|
context "parse" do
|
32
50
|
context "with a query hash like condition" do
|
33
51
|
setup do
|
34
52
|
@sort = RestfulQuery::Sort.parse('long_name_attribute-down')
|
35
53
|
end
|
36
|
-
|
54
|
+
|
37
55
|
should "return sort object" do
|
38
56
|
assert @sort.is_a?(RestfulQuery::Sort)
|
39
57
|
end
|
40
|
-
|
58
|
+
|
41
59
|
should "set column and direction" do
|
42
60
|
assert_equal 'long_name_attribute', @sort.column
|
43
61
|
assert_equal 'DESC', @sort.direction
|
44
62
|
end
|
45
63
|
end
|
46
|
-
|
64
|
+
|
47
65
|
context "with a standard SQL like condition" do
|
48
66
|
setup do
|
49
|
-
@sort = RestfulQuery::Sort.parse('long_name_attribute DESC')
|
67
|
+
@sort = RestfulQuery::Sort.parse('long_name_attribute DESC NULLS LAST')
|
50
68
|
end
|
51
69
|
|
52
70
|
should "return sort object" do
|
@@ -57,16 +75,25 @@ class RestfulQuerySortTest < Test::Unit::TestCase
|
|
57
75
|
assert_equal 'long_name_attribute', @sort.column
|
58
76
|
assert_equal 'DESC', @sort.direction
|
59
77
|
end
|
78
|
+
|
79
|
+
should "set other options" do
|
80
|
+
assert_equal :last, @sort.options[:nulls]
|
81
|
+
end
|
60
82
|
end
|
61
83
|
end
|
62
|
-
|
84
|
+
|
63
85
|
context "to_sql" do
|
64
86
|
should "join the column and attribute" do
|
65
87
|
@sort = RestfulQuery::Sort.new(:attribute, 'down')
|
66
88
|
assert_equal 'attribute DESC', @sort.to_sql
|
67
89
|
end
|
90
|
+
|
91
|
+
should "parse null option" do
|
92
|
+
@sort = RestfulQuery::Sort.new(:attribute, 'down', :nulls => :last)
|
93
|
+
assert_equal 'attribute DESC NULLS LAST', @sort.to_sql
|
94
|
+
end
|
68
95
|
end
|
69
|
-
|
96
|
+
|
70
97
|
end
|
71
|
-
|
72
|
-
end
|
98
|
+
|
99
|
+
end
|
metadata
CHANGED
@@ -1,77 +1,60 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: restful_query
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 3
|
8
|
-
- 3
|
9
|
-
version: 0.3.3
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.4
|
5
|
+
prerelease:
|
10
6
|
platform: ruby
|
11
|
-
authors:
|
7
|
+
authors:
|
12
8
|
- Aaron Quint
|
13
9
|
autorequire:
|
14
10
|
bindir: bin
|
15
11
|
cert_chain: []
|
16
|
-
|
17
|
-
date: 2011-05-17 00:00:00 -07:00
|
12
|
+
date: 2011-08-15 00:00:00.000000000 -04:00
|
18
13
|
default_executable:
|
19
|
-
dependencies:
|
20
|
-
- !ruby/object:Gem::Dependency
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
21
16
|
name: activesupport
|
22
|
-
|
23
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
17
|
+
requirement: &2152029040 !ruby/object:Gem::Requirement
|
24
18
|
none: false
|
25
|
-
requirements:
|
26
|
-
- -
|
27
|
-
- !ruby/object:Gem::Version
|
28
|
-
segments:
|
29
|
-
- 2
|
30
|
-
- 2
|
31
|
-
- 0
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
32
22
|
version: 2.2.0
|
33
23
|
type: :runtime
|
34
|
-
version_requirements: *id001
|
35
|
-
- !ruby/object:Gem::Dependency
|
36
|
-
name: chronic
|
37
24
|
prerelease: false
|
38
|
-
|
25
|
+
version_requirements: *2152029040
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: chronic
|
28
|
+
requirement: &2152028020 !ruby/object:Gem::Requirement
|
39
29
|
none: false
|
40
|
-
requirements:
|
41
|
-
- -
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
segments:
|
44
|
-
- 0
|
45
|
-
- 2
|
46
|
-
- 3
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
47
33
|
version: 0.2.3
|
48
34
|
type: :runtime
|
49
|
-
version_requirements: *id002
|
50
|
-
- !ruby/object:Gem::Dependency
|
51
|
-
name: Shoulda
|
52
35
|
prerelease: false
|
53
|
-
|
36
|
+
version_requirements: *2152028020
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: Shoulda
|
39
|
+
requirement: &2152027080 !ruby/object:Gem::Requirement
|
54
40
|
none: false
|
55
|
-
requirements:
|
56
|
-
- -
|
57
|
-
- !ruby/object:Gem::Version
|
58
|
-
segments:
|
59
|
-
- 1
|
60
|
-
- 2
|
61
|
-
- 0
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
62
44
|
version: 1.2.0
|
63
45
|
type: :development
|
64
|
-
|
65
|
-
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *2152027080
|
48
|
+
description: RestfulQuery provides a simple interface in front of a complex parser
|
49
|
+
to parse specially formatted query hashes into complex SQL queries. It includes
|
50
|
+
ActiveRecord and Sequel extensions.
|
66
51
|
email:
|
67
52
|
executables: []
|
68
|
-
|
69
53
|
extensions: []
|
70
|
-
|
71
|
-
extra_rdoc_files:
|
54
|
+
extra_rdoc_files:
|
72
55
|
- LICENSE
|
73
56
|
- README.rdoc
|
74
|
-
files:
|
57
|
+
files:
|
75
58
|
- History.txt
|
76
59
|
- LICENSE
|
77
60
|
- README.rdoc
|
@@ -95,34 +78,26 @@ files:
|
|
95
78
|
has_rdoc: true
|
96
79
|
homepage:
|
97
80
|
licenses: []
|
98
|
-
|
99
81
|
post_install_message:
|
100
82
|
rdoc_options: []
|
101
|
-
|
102
|
-
require_paths:
|
83
|
+
require_paths:
|
103
84
|
- lib
|
104
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
105
86
|
none: false
|
106
|
-
requirements:
|
107
|
-
- -
|
108
|
-
- !ruby/object:Gem::Version
|
109
|
-
|
110
|
-
|
111
|
-
version: "0"
|
112
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ! '>='
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
113
92
|
none: false
|
114
|
-
requirements:
|
115
|
-
- -
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
|
118
|
-
- 0
|
119
|
-
version: "0"
|
93
|
+
requirements:
|
94
|
+
- - ! '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
120
97
|
requirements: []
|
121
|
-
|
122
98
|
rubyforge_project: quirkey
|
123
|
-
rubygems_version: 1.
|
99
|
+
rubygems_version: 1.6.2
|
124
100
|
signing_key:
|
125
101
|
specification_version: 3
|
126
102
|
summary: Simple ActiveRecord and Sequel queries from a RESTful and safe interface
|
127
103
|
test_files: []
|
128
|
-
|