jdx-sinatra-param 0.0.1
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/Gemfile +3 -0
- data/LICENSE +19 -0
- data/README.md +182 -0
- data/Rakefile +18 -0
- data/example/Gemfile +4 -0
- data/example/Procfile +1 -0
- data/example/app.rb +52 -0
- data/example/config.ru +6 -0
- data/lib/sinatra/param.rb +199 -0
- data/lib/sinatra/param/version.rb +5 -0
- data/sinatra-param.gemspec +26 -0
- data/spec/dummy/app.rb +285 -0
- data/spec/parameter_conjunctivity_spec.rb +34 -0
- data/spec/parameter_exclusivity_spec.rb +55 -0
- data/spec/parameter_inclusivity_spec.rb +30 -0
- data/spec/parameter_raise_spec.rb +25 -0
- data/spec/parameter_spec.rb +19 -0
- data/spec/parameter_transformations_spec.rb +42 -0
- data/spec/parameter_type_coercion_spec.rb +202 -0
- data/spec/parameter_validations_spec.rb +216 -0
- data/spec/spec_helper.rb +20 -0
- metadata +144 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/sinatra/param/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "jdx-sinatra-param"
|
6
|
+
s.license = "MIT"
|
7
|
+
s.authors = ["Mattt"]
|
8
|
+
s.email = "mattt@me.com"
|
9
|
+
s.homepage = "https://github.com/mattt/sinatra-param"
|
10
|
+
s.version = Sinatra::Param::VERSION
|
11
|
+
s.platform = Gem::Platform::RUBY
|
12
|
+
s.summary = "Parameter Validation & Type Coercion for Sinatra."
|
13
|
+
s.description = "sinatra-param allows you to declare, validate, and transform endpoint parameters as you would in frameworks like ActiveModel or DataMapper."
|
14
|
+
|
15
|
+
s.add_dependency "sinatra", ">= 1.3"
|
16
|
+
|
17
|
+
s.add_development_dependency "rake"
|
18
|
+
s.add_development_dependency "rspec"
|
19
|
+
s.add_development_dependency "rack-test"
|
20
|
+
s.add_development_dependency "simplecov"
|
21
|
+
|
22
|
+
s.files = Dir["./**/*"].reject { |file| file =~ /\.\/(bin|log|pkg|script|spec|test|vendor)/ }
|
23
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
24
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
25
|
+
s.require_paths = ["lib"]
|
26
|
+
end
|
data/spec/dummy/app.rb
ADDED
@@ -0,0 +1,285 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'sinatra/param'
|
3
|
+
require 'date'
|
4
|
+
require 'time'
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
class App < Sinatra::Base
|
8
|
+
helpers Sinatra::Param
|
9
|
+
|
10
|
+
set :show_exceptions, false
|
11
|
+
set :raise_errors, true
|
12
|
+
|
13
|
+
before do
|
14
|
+
content_type :json
|
15
|
+
end
|
16
|
+
|
17
|
+
get '/' do
|
18
|
+
param :a, String
|
19
|
+
param :b, String, required: true
|
20
|
+
param :c, String, default: 'test'
|
21
|
+
param :d, String
|
22
|
+
|
23
|
+
params.to_json
|
24
|
+
end
|
25
|
+
|
26
|
+
get '/keys/stringify' do
|
27
|
+
param :q, String, transform: :upcase
|
28
|
+
|
29
|
+
params['q']
|
30
|
+
end
|
31
|
+
|
32
|
+
get '/coerce/string' do
|
33
|
+
params['arg'] = params['arg'].to_i
|
34
|
+
param :arg, String
|
35
|
+
params.to_json
|
36
|
+
end
|
37
|
+
|
38
|
+
get '/coerce/integer' do
|
39
|
+
param :arg, Integer
|
40
|
+
params.to_json
|
41
|
+
end
|
42
|
+
|
43
|
+
get '/coerce/float' do
|
44
|
+
param :arg, Float
|
45
|
+
params.to_json
|
46
|
+
end
|
47
|
+
|
48
|
+
get '/coerce/time' do
|
49
|
+
param :arg, Time
|
50
|
+
params.to_json
|
51
|
+
end
|
52
|
+
|
53
|
+
get '/coerce/date' do
|
54
|
+
param :arg, Date
|
55
|
+
params.to_json
|
56
|
+
end
|
57
|
+
|
58
|
+
get '/coerce/datetime' do
|
59
|
+
param :arg, DateTime
|
60
|
+
params.to_json
|
61
|
+
end
|
62
|
+
|
63
|
+
get '/coerce/array' do
|
64
|
+
param :arg, Array
|
65
|
+
params.to_json
|
66
|
+
end
|
67
|
+
|
68
|
+
get '/coerce/hash' do
|
69
|
+
param :arg, Hash
|
70
|
+
params.to_json
|
71
|
+
end
|
72
|
+
|
73
|
+
get '/coerce/boolean' do
|
74
|
+
param :arg, Boolean
|
75
|
+
params.to_json
|
76
|
+
end
|
77
|
+
|
78
|
+
get '/default' do
|
79
|
+
param :sort, String, default: "title"
|
80
|
+
params.to_json
|
81
|
+
end
|
82
|
+
|
83
|
+
get '/default/hash' do
|
84
|
+
param :attributes, Hash, default: {}
|
85
|
+
params.to_json
|
86
|
+
end
|
87
|
+
|
88
|
+
get '/default/proc' do
|
89
|
+
param :year, Integer, default: proc { 2014 }
|
90
|
+
params.to_json
|
91
|
+
end
|
92
|
+
|
93
|
+
get '/default/boolean/true' do
|
94
|
+
param :arg, Boolean, default: true
|
95
|
+
params.to_json
|
96
|
+
end
|
97
|
+
|
98
|
+
get '/default/boolean/false' do
|
99
|
+
param :arg, Boolean, default: false
|
100
|
+
params.to_json
|
101
|
+
end
|
102
|
+
|
103
|
+
get '/transform' do
|
104
|
+
param :order, String, transform: :upcase
|
105
|
+
params.to_json
|
106
|
+
end
|
107
|
+
|
108
|
+
get '/transform/required' do
|
109
|
+
param :order, String, required: true, transform: :upcase
|
110
|
+
params.to_json
|
111
|
+
end
|
112
|
+
|
113
|
+
get '/validation/required' do
|
114
|
+
param :arg, String, required: true
|
115
|
+
params.to_json
|
116
|
+
end
|
117
|
+
|
118
|
+
get '/validation/blank/string' do
|
119
|
+
param :arg, String, blank: false
|
120
|
+
end
|
121
|
+
|
122
|
+
get '/validation/blank/array' do
|
123
|
+
param :arg, Array, blank: false
|
124
|
+
end
|
125
|
+
|
126
|
+
get '/validation/blank/hash' do
|
127
|
+
param :arg, Hash, blank: false
|
128
|
+
end
|
129
|
+
|
130
|
+
get '/validation/blank/other' do
|
131
|
+
param :arg, Class, blank: false
|
132
|
+
end
|
133
|
+
|
134
|
+
get '/validation/nonblank/string' do
|
135
|
+
param :arg, String, blank: true
|
136
|
+
end
|
137
|
+
|
138
|
+
get '/validation/format/9000' do
|
139
|
+
param :arg, Integer, format: /9000/
|
140
|
+
params.to_json
|
141
|
+
end
|
142
|
+
|
143
|
+
get '/validation/format/hello' do
|
144
|
+
param :arg, String, format: /hello/
|
145
|
+
params.to_json
|
146
|
+
end
|
147
|
+
|
148
|
+
get '/validation/is' do
|
149
|
+
param :arg, String, is: 'foo'
|
150
|
+
params.to_json
|
151
|
+
end
|
152
|
+
|
153
|
+
get '/validation/in' do
|
154
|
+
param :arg, String, in: ['ASC', 'DESC']
|
155
|
+
params.to_json
|
156
|
+
end
|
157
|
+
|
158
|
+
get '/validation/within' do
|
159
|
+
param :arg, Integer, within: 1..10
|
160
|
+
params.to_json
|
161
|
+
end
|
162
|
+
|
163
|
+
get '/validation/range' do
|
164
|
+
param :arg, Integer, range: 1..10
|
165
|
+
params.to_json
|
166
|
+
end
|
167
|
+
|
168
|
+
get '/validation/min' do
|
169
|
+
param :arg, Integer, min: 12
|
170
|
+
params.to_json
|
171
|
+
end
|
172
|
+
|
173
|
+
get '/validation/max' do
|
174
|
+
param :arg, Integer, max: 20
|
175
|
+
params.to_json
|
176
|
+
end
|
177
|
+
|
178
|
+
get '/validation/min_length' do
|
179
|
+
param :arg, String, min_length: 5
|
180
|
+
params.to_json
|
181
|
+
end
|
182
|
+
|
183
|
+
get '/validation/max_length' do
|
184
|
+
param :arg, String, max_length: 10
|
185
|
+
params.to_json
|
186
|
+
end
|
187
|
+
|
188
|
+
get '/one_of/1' do
|
189
|
+
param :a, String
|
190
|
+
param :b, String
|
191
|
+
param :c, String
|
192
|
+
|
193
|
+
one_of :a
|
194
|
+
|
195
|
+
{
|
196
|
+
message: 'OK'
|
197
|
+
}.to_json
|
198
|
+
end
|
199
|
+
|
200
|
+
get '/one_of/2' do
|
201
|
+
param :a, String
|
202
|
+
param :b, String
|
203
|
+
param :c, String
|
204
|
+
|
205
|
+
one_of :a, :b
|
206
|
+
|
207
|
+
{
|
208
|
+
message: 'OK'
|
209
|
+
}.to_json
|
210
|
+
end
|
211
|
+
|
212
|
+
get '/one_of/3' do
|
213
|
+
param :a, String
|
214
|
+
param :b, String
|
215
|
+
param :c, String
|
216
|
+
|
217
|
+
one_of :a, :b, :c
|
218
|
+
|
219
|
+
{
|
220
|
+
message: 'OK'
|
221
|
+
}.to_json
|
222
|
+
end
|
223
|
+
|
224
|
+
get '/any_of' do
|
225
|
+
param :a, String
|
226
|
+
param :b, String
|
227
|
+
param :c, String
|
228
|
+
|
229
|
+
any_of :a, :b, :c
|
230
|
+
|
231
|
+
{
|
232
|
+
message: 'OK'
|
233
|
+
}.to_json
|
234
|
+
end
|
235
|
+
|
236
|
+
get '/raise/validation/required' do
|
237
|
+
param :arg, String, required: true, raise: true
|
238
|
+
params.to_json
|
239
|
+
end
|
240
|
+
|
241
|
+
get '/raise/one_of/3' do
|
242
|
+
param :a, String
|
243
|
+
param :b, String
|
244
|
+
param :c, String
|
245
|
+
|
246
|
+
one_of :a, :b, :c, raise: true
|
247
|
+
|
248
|
+
{
|
249
|
+
message: 'OK'
|
250
|
+
}.to_json
|
251
|
+
end
|
252
|
+
|
253
|
+
get '/raise/any_of' do
|
254
|
+
param :a, String
|
255
|
+
param :b, String
|
256
|
+
param :c, String
|
257
|
+
|
258
|
+
any_of :a, :b, :c, raise: true
|
259
|
+
|
260
|
+
{
|
261
|
+
message: 'OK'
|
262
|
+
}.to_json
|
263
|
+
end
|
264
|
+
|
265
|
+
get '/xml' do
|
266
|
+
content_type :xml
|
267
|
+
param :a, Integer, within: 1..10, required: true
|
268
|
+
end
|
269
|
+
|
270
|
+
get '/custommessage' do
|
271
|
+
param :a, Integer, within: 1..10, required: true, message: "'a' must be less than 10"
|
272
|
+
end
|
273
|
+
|
274
|
+
get '/all_or_none_of' do
|
275
|
+
param :a, String
|
276
|
+
param :b, String
|
277
|
+
param :c, String
|
278
|
+
|
279
|
+
all_or_none_of :a, :b, :c
|
280
|
+
|
281
|
+
{
|
282
|
+
message: 'OK'
|
283
|
+
}.to_json
|
284
|
+
end
|
285
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Parameter Sets' do
|
4
|
+
describe 'all_or_none_of' do
|
5
|
+
it 'returns 400 on requests that have some but not all required parameters' do
|
6
|
+
params = [
|
7
|
+
{a: 1},
|
8
|
+
{b: 2, c: 3},
|
9
|
+
{a: 1, c: 3},
|
10
|
+
]
|
11
|
+
|
12
|
+
params.each do |param|
|
13
|
+
get('/all_or_none_of', param) do |response|
|
14
|
+
expect(response.status).to eql 400
|
15
|
+
expect(JSON.parse(response.body)['message']).to match(/^Invalid parameters/)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'returns successfully for requests that have all parameters' do
|
21
|
+
param = {a: 1, b: 2, c: 3}
|
22
|
+
|
23
|
+
response = get("/all_or_none_of", param)
|
24
|
+
expect(response.status).to eql 200
|
25
|
+
expect(JSON.parse(response.body)['message']).to match(/OK/)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'returns successfully for requests that have none of the parameters' do
|
29
|
+
response = get("/all_or_none_of")
|
30
|
+
expect(response.status).to eql 200
|
31
|
+
expect(JSON.parse(response.body)['message']).to match(/OK/)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Parameter Sets' do
|
4
|
+
describe 'one_of' do
|
5
|
+
it 'returns 400 on requests that contain more than one mutually exclusive parameter' do
|
6
|
+
params = [
|
7
|
+
{a: 1, b: 2},
|
8
|
+
{b: 2, c: 3},
|
9
|
+
{a: 1, b: 2, c: 3}
|
10
|
+
]
|
11
|
+
|
12
|
+
params.each do |param|
|
13
|
+
get('/one_of/3', param) do |response|
|
14
|
+
expect(response.status).to eql 400
|
15
|
+
expect(JSON.parse(response.body)['message']).to match(/^Invalid parameters/)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'returns 400 on requests that contain more than one mutually exclusive parameter' do
|
21
|
+
params = {a: 1, b: 2}
|
22
|
+
|
23
|
+
get('/one_of/2', params) do |response|
|
24
|
+
expect(response.status).to eql 400
|
25
|
+
expect(JSON.parse(response.body)['message']).to match(/^Invalid parameters/)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'returns successfully for requests that have one parameter' do
|
30
|
+
params = [
|
31
|
+
{a: 1},
|
32
|
+
{b: 2},
|
33
|
+
{c: 3}
|
34
|
+
]
|
35
|
+
|
36
|
+
(1..3).each do |n|
|
37
|
+
params.each do |param|
|
38
|
+
get("/one_of/#{n}", param) do |response|
|
39
|
+
expect(response.status).to eql 200
|
40
|
+
expect(JSON.parse(response.body)['message']).to match(/OK/)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'returns successfully for requests that have no parameter' do
|
47
|
+
(1..3).each do |n|
|
48
|
+
get("/one_of/#{n}") do |response|
|
49
|
+
expect(response.status).to eql 200
|
50
|
+
expect(JSON.parse(response.body)['message']).to match(/OK/)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Parameter Sets' do
|
4
|
+
describe 'any_of' do
|
5
|
+
it 'returns 400 on requests that contain fewer than one required parameter' do
|
6
|
+
get('/any_of', {}) do |response|
|
7
|
+
expect(response.status).to eql 400
|
8
|
+
expect(JSON.parse(response.body)['message']).to match(/Invalid parameters/)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'returns successfully for requests that have at least one parameter' do
|
13
|
+
params = [
|
14
|
+
{a: 1},
|
15
|
+
{b: 2},
|
16
|
+
{c: 3},
|
17
|
+
{a: 1, b: 2},
|
18
|
+
{b: 2, c: 3},
|
19
|
+
{a: 1, b: 2, c: 3}
|
20
|
+
]
|
21
|
+
|
22
|
+
params.each do |param|
|
23
|
+
get("/any_of", param) do |response|
|
24
|
+
expect(response.status).to eql 200
|
25
|
+
expect(JSON.parse(response.body)['message']).to match(/OK/)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Exception' do
|
4
|
+
describe 'raise' do
|
5
|
+
it 'should raise error when option is specified' do
|
6
|
+
expect {
|
7
|
+
get('/raise/validation/required')
|
8
|
+
}.to raise_error Sinatra::Param::InvalidParameterError
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should raise error when more than one parameter is specified' do
|
13
|
+
params = {a: 1, b: 2, c: 3}
|
14
|
+
expect {
|
15
|
+
get('/raise/one_of/3', params)
|
16
|
+
}.to raise_error Sinatra::Param::InvalidParameterError
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should raise error when no parameters are specified' do
|
20
|
+
params = {}
|
21
|
+
expect {
|
22
|
+
get('/raise/any_of', params)
|
23
|
+
}.to raise_error Sinatra::Param::InvalidParameterError
|
24
|
+
end
|
25
|
+
end
|