groonga-client 0.3.9 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/doc/text/news.md +14 -0
- data/lib/groonga/client/request/select.rb +112 -20
- data/lib/groonga/client/version.rb +1 -1
- data/test/request/select/{test-sort-keys-columns-parameter.rb → test-backward-compatible-sort-keys-parameter.rb} +3 -3
- data/test/request/select/test-sort-keys-parameter.rb +70 -0
- data/test/request/test-select.rb +123 -1
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b10f2746556ebf27bbe22c67f37fe6758aab8400
|
4
|
+
data.tar.gz: 5f96d9789517af65942d155c12053d88283b2d3e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6dddafd8f52e38d9d9a6a53cf24a5ab475de32a106d955743c289a64c87d1907cfc13777a4a1c1cfc3be711ec9d6d4287d832e10861f308b1710c240b8b05117
|
7
|
+
data.tar.gz: 69fb56a8c4322708287bf815f883d1c04748476bba5b54048ae35070314d45b96374ada729ade886c4562047001a8f9752367cab04a1fb19c35ccc8221a52d8f
|
data/doc/text/news.md
CHANGED
@@ -1,5 +1,19 @@
|
|
1
1
|
# NEWS
|
2
2
|
|
3
|
+
## 0.4.0 - 2016-01-12
|
4
|
+
|
5
|
+
### Improvements
|
6
|
+
|
7
|
+
* `Groonga::Client::Request::Select#columns`: Supported
|
8
|
+
`columns[label]`.
|
9
|
+
|
10
|
+
### Fixes
|
11
|
+
|
12
|
+
* Removed Active Support method use.
|
13
|
+
|
14
|
+
* `Groonga::Client::Request::Select#filter`: Fixed filter value
|
15
|
+
escape error.
|
16
|
+
|
3
17
|
## 0.3.9 - 2016-12-22
|
4
18
|
|
5
19
|
### Improvements
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2016 Kouhei Sutou <kou@clear-code.com>
|
1
|
+
# Copyright (C) 2016-2017 Kouhei Sutou <kou@clear-code.com>
|
2
2
|
#
|
3
3
|
# This library is free software; you can redistribute it and/or
|
4
4
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -98,7 +98,7 @@ module Groonga
|
|
98
98
|
|
99
99
|
def sort_keys(value)
|
100
100
|
add_parameter(OverwriteMerger,
|
101
|
-
|
101
|
+
BackwardCompatibleSortKeysParameter.new("", value))
|
102
102
|
end
|
103
103
|
alias_method :sortby, :sort_keys
|
104
104
|
alias_method :sort, :sort_keys
|
@@ -126,6 +126,10 @@ module Groonga
|
|
126
126
|
LabeledDrilldown.new(self, label)
|
127
127
|
end
|
128
128
|
|
129
|
+
def columns(label)
|
130
|
+
DynamicColumn.new(self, label)
|
131
|
+
end
|
132
|
+
|
129
133
|
def each(&block)
|
130
134
|
response.records.each(&block)
|
131
135
|
end
|
@@ -158,7 +162,7 @@ module Groonga
|
|
158
162
|
|
159
163
|
def sort_keys(value)
|
160
164
|
add_parameter(OverwriteMerger,
|
161
|
-
|
165
|
+
BackwardCompatibleSortKeysParameter.new(prefix, value))
|
162
166
|
end
|
163
167
|
alias_method :sortby, :sort_keys
|
164
168
|
alias_method :sort, :sort_keys
|
@@ -195,6 +199,71 @@ module Groonga
|
|
195
199
|
end
|
196
200
|
end
|
197
201
|
|
202
|
+
class DynamicColumn
|
203
|
+
def initialize(request, label)
|
204
|
+
@request = request
|
205
|
+
@label = label
|
206
|
+
end
|
207
|
+
|
208
|
+
def stage(value)
|
209
|
+
add_parameter(OverwriteMerger,
|
210
|
+
RequestParameter.new(:"#{prefix}stage", value))
|
211
|
+
end
|
212
|
+
|
213
|
+
def type(value)
|
214
|
+
add_parameter(OverwriteMerger,
|
215
|
+
RequestParameter.new(:"#{prefix}type", value))
|
216
|
+
end
|
217
|
+
|
218
|
+
def flags(value)
|
219
|
+
add_parameter(OverwriteMerger,
|
220
|
+
FlagsParameter.new([:"#{prefix}flags"], value))
|
221
|
+
end
|
222
|
+
|
223
|
+
def value(expression, values=nil)
|
224
|
+
add_parameter(OverwriteMerger,
|
225
|
+
ScriptSyntaxExpressionParameter.new(:"#{prefix}value",
|
226
|
+
expression,
|
227
|
+
values))
|
228
|
+
end
|
229
|
+
|
230
|
+
def window
|
231
|
+
DynamicColumnWindow.new(@request, @label)
|
232
|
+
end
|
233
|
+
|
234
|
+
private
|
235
|
+
def prefix
|
236
|
+
"columns[#{@label}]."
|
237
|
+
end
|
238
|
+
|
239
|
+
def add_parameter(merger, parameter)
|
240
|
+
@request.__send__(:add_parameter, merger, parameter)
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
class DynamicColumnWindow
|
245
|
+
def initialize(request, label)
|
246
|
+
@request = request
|
247
|
+
@label = label
|
248
|
+
end
|
249
|
+
|
250
|
+
def sort_keys(value)
|
251
|
+
add_parameter(OverwriteMerger,
|
252
|
+
SortKeysParameter.new(prefix, value))
|
253
|
+
end
|
254
|
+
alias_method :sortby, :sort_keys
|
255
|
+
alias_method :sort, :sort_keys
|
256
|
+
|
257
|
+
private
|
258
|
+
def prefix
|
259
|
+
"columns[#{@label}].window."
|
260
|
+
end
|
261
|
+
|
262
|
+
def add_parameter(merger, parameter)
|
263
|
+
@request.__send__(:add_parameter, merger, parameter)
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
198
267
|
# @private
|
199
268
|
class QueryMerger < ParameterMerger
|
200
269
|
def to_parameters
|
@@ -203,7 +272,7 @@ module Groonga
|
|
203
272
|
params = params1.merge(params2)
|
204
273
|
query1 = params1[:query]
|
205
274
|
query2 = params2[:query]
|
206
|
-
if query1
|
275
|
+
if query1 and query2
|
207
276
|
params[:query] = "(#{query1}) (#{query2})"
|
208
277
|
else
|
209
278
|
params[:query] = (query1 || query2)
|
@@ -220,7 +289,7 @@ module Groonga
|
|
220
289
|
params = params1.merge(params2)
|
221
290
|
filter1 = params1[:filter]
|
222
291
|
filter2 = params2[:filter]
|
223
|
-
if filter1
|
292
|
+
if filter1 and filter2
|
224
293
|
params[:filter] = "(#{filter1}) && (#{filter2})"
|
225
294
|
else
|
226
295
|
params[:filter] = (filter1 || filter2)
|
@@ -230,14 +299,14 @@ module Groonga
|
|
230
299
|
end
|
231
300
|
|
232
301
|
# @private
|
233
|
-
module
|
302
|
+
module ScriptSyntaxValueEscapable
|
234
303
|
private
|
235
|
-
def
|
304
|
+
def escape_script_syntax_value(value)
|
236
305
|
case value
|
237
306
|
when Numeric
|
238
|
-
value
|
307
|
+
value.to_s
|
239
308
|
when TrueClass, FalseClass
|
240
|
-
value
|
309
|
+
value.to_s
|
241
310
|
when NilClass
|
242
311
|
"null"
|
243
312
|
when String
|
@@ -248,7 +317,7 @@ module Groonga
|
|
248
317
|
escaped_value = "["
|
249
318
|
value.each_with_index do |element, i|
|
250
319
|
escaped_value << ", " if i > 0
|
251
|
-
escaped_value <<
|
320
|
+
escaped_value << escape_script_syntax_value(element)
|
252
321
|
end
|
253
322
|
escaped_value << "]"
|
254
323
|
escaped_value
|
@@ -256,9 +325,9 @@ module Groonga
|
|
256
325
|
escaped_value = "{"
|
257
326
|
value.each_with_index do |(k, v), i|
|
258
327
|
escaped_value << ", " if i > 0
|
259
|
-
escaped_value <<
|
328
|
+
escaped_value << escape_script_syntax_value(k.to_s)
|
260
329
|
escaped_value << ": "
|
261
|
-
escaped_value <<
|
330
|
+
escaped_value << escape_script_syntax_value(v)
|
262
331
|
end
|
263
332
|
escaped_value << "}"
|
264
333
|
escaped_value
|
@@ -269,10 +338,11 @@ module Groonga
|
|
269
338
|
end
|
270
339
|
|
271
340
|
# @private
|
272
|
-
class
|
273
|
-
include
|
341
|
+
class ScriptSyntaxExpressionParameter
|
342
|
+
include ScriptSyntaxValueEscapable
|
274
343
|
|
275
|
-
def initialize(expression, values)
|
344
|
+
def initialize(name, expression, values)
|
345
|
+
@name = name
|
276
346
|
@expression = expression
|
277
347
|
@values = values
|
278
348
|
end
|
@@ -288,23 +358,35 @@ module Groonga
|
|
288
358
|
expression = @expression
|
289
359
|
end
|
290
360
|
|
291
|
-
|
361
|
+
case @values
|
362
|
+
when ::Hash
|
292
363
|
escaped_values = {}
|
293
364
|
@values.each do |key, value|
|
294
|
-
escaped_values[key] =
|
365
|
+
escaped_values[key] = escape_script_syntax_value(value)
|
366
|
+
end
|
367
|
+
expression = expression % escaped_values
|
368
|
+
when ::Array
|
369
|
+
escaped_values = @values.collect do |value|
|
370
|
+
escape_script_syntax_value(value)
|
295
371
|
end
|
296
372
|
expression = expression % escaped_values
|
297
373
|
end
|
298
374
|
|
299
375
|
{
|
300
|
-
|
376
|
+
@name => expression,
|
301
377
|
}
|
302
378
|
end
|
303
379
|
end
|
304
380
|
|
381
|
+
class FilterExpressionParameter < ScriptSyntaxExpressionParameter
|
382
|
+
def initialize(expression, values)
|
383
|
+
super(:filter, expression, values)
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
305
387
|
# @private
|
306
388
|
class FilterEqualParameter
|
307
|
-
include
|
389
|
+
include ScriptSyntaxValueEscapable
|
308
390
|
|
309
391
|
def initialize(column_name, value)
|
310
392
|
@column_name = column_name
|
@@ -313,7 +395,7 @@ module Groonga
|
|
313
395
|
|
314
396
|
def to_parameters
|
315
397
|
{
|
316
|
-
filter: "#{@column_name} == #{
|
398
|
+
filter: "#{@column_name} == #{escape_script_syntax_value(@value)}",
|
317
399
|
}
|
318
400
|
end
|
319
401
|
end
|
@@ -339,6 +421,16 @@ module Groonga
|
|
339
421
|
|
340
422
|
# @private
|
341
423
|
class SortKeysParameter < ValuesParameter
|
424
|
+
def initialize(prefix, output_columns)
|
425
|
+
names = [
|
426
|
+
:"#{prefix}sort_keys",
|
427
|
+
]
|
428
|
+
super(names, output_columns)
|
429
|
+
end
|
430
|
+
end
|
431
|
+
|
432
|
+
# @private
|
433
|
+
class BackwardCompatibleSortKeysParameter < ValuesParameter
|
342
434
|
def initialize(prefix, output_columns)
|
343
435
|
names = [
|
344
436
|
:"#{prefix}sort_keys",
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C)
|
1
|
+
# Copyright (C) 2017 Kouhei Sutou <kou@clear-code.com>
|
2
2
|
#
|
3
3
|
# This library is free software; you can redistribute it and/or
|
4
4
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -14,9 +14,9 @@
|
|
14
14
|
# License along with this library; if not, write to the Free Software
|
15
15
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
16
16
|
|
17
|
-
class
|
17
|
+
class TestRequestSelectBackwardCompatibleSortKeysParmater < Test::Unit::TestCase
|
18
18
|
def sort_keys_parameter(prefix, sort_keys)
|
19
|
-
Groonga::Client::Request::Select::
|
19
|
+
Groonga::Client::Request::Select::BackwardCompatibleSortKeysParameter.new(prefix, sort_keys)
|
20
20
|
end
|
21
21
|
|
22
22
|
def to_parameters(sort_keys)
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# Copyright (C) 2016-2017 Kouhei Sutou <kou@clear-code.com>
|
2
|
+
#
|
3
|
+
# This library is free software; you can redistribute it and/or
|
4
|
+
# modify it under the terms of the GNU Lesser General Public
|
5
|
+
# License as published by the Free Software Foundation; either
|
6
|
+
# version 2.1 of the License, or (at your option) any later version.
|
7
|
+
#
|
8
|
+
# This library is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
11
|
+
# Lesser General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU Lesser General Public
|
14
|
+
# License along with this library; if not, write to the Free Software
|
15
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
16
|
+
|
17
|
+
class TestRequestSelectSortKeysParmater < Test::Unit::TestCase
|
18
|
+
def sort_keys_parameter(prefix, sort_keys)
|
19
|
+
Groonga::Client::Request::Select::SortKeysParameter.new(prefix, sort_keys)
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_parameters(sort_keys)
|
23
|
+
sort_keys_parameter("", sort_keys).to_parameters
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_nil
|
27
|
+
assert_equal({},
|
28
|
+
to_parameters(nil))
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_string
|
32
|
+
assert_equal({
|
33
|
+
:sort_keys => "-_score, _id",
|
34
|
+
},
|
35
|
+
to_parameters("-_score, _id"))
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_empty_string
|
39
|
+
assert_equal({},
|
40
|
+
to_parameters(""))
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_symbol
|
44
|
+
assert_equal({
|
45
|
+
:sort_keys => "_score",
|
46
|
+
},
|
47
|
+
to_parameters(:_score))
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_array
|
51
|
+
assert_equal({
|
52
|
+
:sort_keys => "-_score, _id",
|
53
|
+
},
|
54
|
+
to_parameters(["-_score", :_id]))
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_empty_array
|
58
|
+
assert_equal({},
|
59
|
+
to_parameters([]))
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_prefix
|
63
|
+
parameter = sort_keys_parameter("slices[tag].", "-_score, _id")
|
64
|
+
|
65
|
+
assert_equal({
|
66
|
+
:"slices[tag].sort_keys" => "-_score, _id",
|
67
|
+
},
|
68
|
+
parameter.to_parameters)
|
69
|
+
end
|
70
|
+
end
|
data/test/request/test-select.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2016 Kouhei Sutou <kou@clear-code.com>
|
1
|
+
# Copyright (C) 2016-2017 Kouhei Sutou <kou@clear-code.com>
|
2
2
|
#
|
3
3
|
# This library is free software; you can redistribute it and/or
|
4
4
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -19,6 +19,80 @@ class TestRequestSelect < Test::Unit::TestCase
|
|
19
19
|
@request = Groonga::Client::Request::Select.new("posts")
|
20
20
|
end
|
21
21
|
|
22
|
+
sub_test_case("#filter") do
|
23
|
+
def filter(*args)
|
24
|
+
@request.filter(*args).to_parameters
|
25
|
+
end
|
26
|
+
|
27
|
+
test("Numeric") do
|
28
|
+
assert_equal({
|
29
|
+
:table => "posts",
|
30
|
+
:filter => "rate == 5",
|
31
|
+
},
|
32
|
+
filter("rate == %{rate}", :rate => 5))
|
33
|
+
end
|
34
|
+
|
35
|
+
test("true") do
|
36
|
+
assert_equal({
|
37
|
+
:table => "posts",
|
38
|
+
:filter => "published == true",
|
39
|
+
},
|
40
|
+
filter("published == %{published}", :published => true))
|
41
|
+
end
|
42
|
+
|
43
|
+
test("false") do
|
44
|
+
assert_equal({
|
45
|
+
:table => "posts",
|
46
|
+
:filter => "published == false",
|
47
|
+
},
|
48
|
+
filter("published == %{published}", :published => false))
|
49
|
+
end
|
50
|
+
|
51
|
+
test("nil") do
|
52
|
+
assert_equal({
|
53
|
+
:table => "posts",
|
54
|
+
:filter => "function(null)",
|
55
|
+
},
|
56
|
+
filter("function(%{arg})", :arg => nil))
|
57
|
+
end
|
58
|
+
|
59
|
+
test("String") do
|
60
|
+
assert_equal({
|
61
|
+
:table => "posts",
|
62
|
+
:filter => "title == \"Hello\"",
|
63
|
+
},
|
64
|
+
filter("title == %{title}", :title => "Hello"))
|
65
|
+
end
|
66
|
+
|
67
|
+
test("Symbol") do
|
68
|
+
assert_equal({
|
69
|
+
:table => "posts",
|
70
|
+
:filter => "title == \"Hello\"",
|
71
|
+
},
|
72
|
+
filter("title == %{title}", :title => :Hello))
|
73
|
+
end
|
74
|
+
|
75
|
+
test("Array") do
|
76
|
+
assert_equal({
|
77
|
+
:table => "posts",
|
78
|
+
:filter => "function([\"a\", 29])",
|
79
|
+
},
|
80
|
+
filter("function(%{arg})", :arg => ["a", 29]))
|
81
|
+
end
|
82
|
+
|
83
|
+
test("Hash") do
|
84
|
+
assert_equal({
|
85
|
+
:table => "posts",
|
86
|
+
:filter => "function({\"string\": \"value\", \"number\": 29})",
|
87
|
+
},
|
88
|
+
filter("function(%{options})",
|
89
|
+
:options => {
|
90
|
+
"string" => "value",
|
91
|
+
"number" => 29
|
92
|
+
}))
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
22
96
|
sub_test_case("#drilldowns") do
|
23
97
|
def drilldown
|
24
98
|
@request.drilldowns("label")
|
@@ -128,4 +202,52 @@ class TestRequestSelect < Test::Unit::TestCase
|
|
128
202
|
end
|
129
203
|
end
|
130
204
|
end
|
205
|
+
|
206
|
+
sub_test_case("#columns") do
|
207
|
+
def column
|
208
|
+
@request.columns("label")
|
209
|
+
end
|
210
|
+
|
211
|
+
test "#stage" do
|
212
|
+
assert_equal({
|
213
|
+
:table => "posts",
|
214
|
+
:"columns[label].stage" => "output",
|
215
|
+
},
|
216
|
+
column.stage("output").to_parameters)
|
217
|
+
end
|
218
|
+
|
219
|
+
test "#type" do
|
220
|
+
assert_equal({
|
221
|
+
:table => "posts",
|
222
|
+
:"columns[label].type" => "Text",
|
223
|
+
},
|
224
|
+
column.type("Text").to_parameters)
|
225
|
+
end
|
226
|
+
|
227
|
+
test "#flags" do
|
228
|
+
assert_equal({
|
229
|
+
:table => "posts",
|
230
|
+
:"columns[label].flags" => "COLUMN_SCALAR|COMPRESS_LZ4",
|
231
|
+
},
|
232
|
+
column.flags(["COLUMN_SCALAR", "COMPRESS_LZ4"]).to_parameters)
|
233
|
+
end
|
234
|
+
|
235
|
+
test "#value" do
|
236
|
+
assert_equal({
|
237
|
+
:table => "posts",
|
238
|
+
:"columns[label].value" => "highlight_html(\"xxx\")",
|
239
|
+
},
|
240
|
+
column.value("highlight_html(%{text})", text: "xxx").to_parameters)
|
241
|
+
end
|
242
|
+
|
243
|
+
sub_test_case("#window") do
|
244
|
+
test "#sort_keys" do
|
245
|
+
assert_equal({
|
246
|
+
:table => "posts",
|
247
|
+
:"columns[label].window.sort_keys" => "_id",
|
248
|
+
},
|
249
|
+
column.window.sort_keys("_id").to_parameters)
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
131
253
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: groonga-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Haruka Yoshihara
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2017-01-12 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: gqtp
|
@@ -223,10 +223,11 @@ files:
|
|
223
223
|
- lib/groonga/client/version.rb
|
224
224
|
- test/protocol/test-gqtp.rb
|
225
225
|
- test/protocol/test-http.rb
|
226
|
+
- test/request/select/test-backward-compatible-sort-keys-parameter.rb
|
226
227
|
- test/request/select/test-filter-equal-parameter.rb
|
227
228
|
- test/request/select/test-filter-expression-parameter.rb
|
228
229
|
- test/request/select/test-output-columns-parameter.rb
|
229
|
-
- test/request/select/test-sort-keys-
|
230
|
+
- test/request/select/test-sort-keys-parameter.rb
|
230
231
|
- test/request/select/test-values-parameter.rb
|
231
232
|
- test/request/test-base.rb
|
232
233
|
- test/request/test-select.rb
|
@@ -277,10 +278,11 @@ test_files:
|
|
277
278
|
- test/test-client.rb
|
278
279
|
- test/test-script-syntax.rb
|
279
280
|
- test/request/select/test-filter-expression-parameter.rb
|
281
|
+
- test/request/select/test-backward-compatible-sort-keys-parameter.rb
|
282
|
+
- test/request/select/test-sort-keys-parameter.rb
|
280
283
|
- test/request/select/test-output-columns-parameter.rb
|
281
284
|
- test/request/select/test-values-parameter.rb
|
282
285
|
- test/request/select/test-filter-equal-parameter.rb
|
283
|
-
- test/request/select/test-sort-keys-columns-parameter.rb
|
284
286
|
- test/request/test-base.rb
|
285
287
|
- test/request/test-select.rb
|
286
288
|
- test/test-command.rb
|