sinatra-param 0.1.1 → 0.1.2
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/Gemfile +9 -1
- data/Gemfile.lock +7 -1
- data/README.md +4 -9
- data/Rakefile +0 -1
- data/coverage/assets/0.7.1/application.css +1110 -0
- data/coverage/assets/0.7.1/application.js +626 -0
- data/coverage/assets/0.7.1/fancybox/blank.gif +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_close.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_loading.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_nav_left.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_nav_right.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_shadow_e.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_shadow_n.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_shadow_ne.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_shadow_nw.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_shadow_s.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_shadow_se.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_shadow_sw.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_shadow_w.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_title_left.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_title_main.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_title_over.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_title_right.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancybox-x.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancybox-y.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancybox.png +0 -0
- data/coverage/assets/0.7.1/favicon_green.png +0 -0
- data/coverage/assets/0.7.1/favicon_red.png +0 -0
- data/coverage/assets/0.7.1/favicon_yellow.png +0 -0
- data/coverage/assets/0.7.1/loading.gif +0 -0
- data/coverage/assets/0.7.1/magnify.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-icons_222222_256x240.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-icons_454545_256x240.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-icons_888888_256x240.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/coverage/index.html +788 -0
- data/{lib/example → example}/Gemfile +0 -0
- data/{lib/example → example}/Gemfile.lock +0 -0
- data/{lib/example → example}/Procfile +0 -0
- data/{lib/example → example}/app.rb +7 -7
- data/{lib/example → example}/config.ru +0 -0
- data/lib/sinatra/param.rb +36 -32
- data/lib/sinatra/param/version.rb +1 -1
- data/sinatra-param.gemspec +3 -6
- data/spec/dummy/app.rb +146 -0
- data/spec/parameter_sets_spec.rb +33 -0
- data/spec/parameter_transformations_spec.rb +21 -0
- data/spec/parameter_type_coercion_spec.rb +90 -0
- data/spec/parameter_validations_spec.rb +174 -0
- data/spec/spec_helper.rb +19 -2
- metadata +65 -39
- data/sinatra-param-0.1.0.gem +0 -0
- data/spec/exclude_spec.rb +0 -36
File without changes
|
File without changes
|
File without changes
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'sinatra/base'
|
2
2
|
require 'json'
|
3
3
|
|
4
|
-
require_relative '../sinatra/param'
|
4
|
+
require_relative '../lib/sinatra/param'
|
5
5
|
|
6
6
|
class App < Sinatra::Base
|
7
7
|
helpers Sinatra::Param
|
@@ -9,32 +9,32 @@ class App < Sinatra::Base
|
|
9
9
|
before do
|
10
10
|
content_type :json
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
# GET /messages
|
14
14
|
# GET /messages?sort=name&order=ASC
|
15
15
|
get '/messages' do
|
16
16
|
param :sort, String, default: "name"
|
17
17
|
param :order, String, in: ["ASC", "DESC"], transform: :upcase, default: "ASC"
|
18
|
-
|
18
|
+
|
19
19
|
{
|
20
20
|
sort: params[:sort],
|
21
21
|
order: params[:order]
|
22
22
|
}.to_json
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
# GET /messages/1,2,3,4,5
|
26
26
|
get '/messages/:ids' do
|
27
27
|
param :ids, Array, required: true
|
28
|
-
|
28
|
+
|
29
29
|
{
|
30
30
|
ids: params[:ids]
|
31
31
|
}.to_json
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
# POST /messages/1/response
|
35
35
|
post '/messages/:id/response' do
|
36
36
|
param :message, String, max: 1024, required: true
|
37
|
-
|
37
|
+
|
38
38
|
{
|
39
39
|
message: params[:message]
|
40
40
|
}.to_json
|
File without changes
|
data/lib/sinatra/param.rb
CHANGED
@@ -14,7 +14,7 @@ module Sinatra
|
|
14
14
|
validate!(params[name], options)
|
15
15
|
rescue
|
16
16
|
error = "Invalid parameter, #{name}"
|
17
|
-
if content_type
|
17
|
+
if content_type and content_type.match(mime_type(:json))
|
18
18
|
error = {message: error}.to_json
|
19
19
|
end
|
20
20
|
|
@@ -23,14 +23,17 @@ module Sinatra
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def one_of(*names)
|
26
|
-
|
26
|
+
count = 0
|
27
27
|
names.each do |name|
|
28
|
-
|
29
|
-
|
28
|
+
if params[name] and present?(params[name])
|
29
|
+
count += 1
|
30
|
+
next unless count > 1
|
31
|
+
|
30
32
|
error = "Parameters #{names.join(', ')} are mutually exclusive"
|
31
|
-
if content_type.match(mime_type(:json))
|
33
|
+
if content_type and content_type.match(mime_type(:json))
|
32
34
|
error = {message: error}.to_json
|
33
35
|
end
|
36
|
+
|
34
37
|
halt 406, error
|
35
38
|
end
|
36
39
|
end
|
@@ -58,44 +61,45 @@ module Sinatra
|
|
58
61
|
case key
|
59
62
|
when :required
|
60
63
|
raise InvalidParameterError if value && param.nil?
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
64
|
+
when :blank
|
65
|
+
raise InvalidParameterError if !value && case param
|
66
|
+
when String
|
67
|
+
!(/\S/ === param)
|
68
|
+
when Array, Hash
|
69
|
+
param.empty?
|
70
|
+
else
|
71
|
+
param.nil?
|
72
|
+
end
|
73
|
+
when :is
|
74
|
+
raise InvalidParameterError unless value === param
|
75
|
+
when :in, :within, :range
|
76
|
+
raise InvalidParameterError unless param.nil? || case value
|
77
|
+
when Range
|
78
|
+
value.include?(param)
|
79
|
+
else
|
80
|
+
Array(value).include?(param)
|
69
81
|
end
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
end
|
79
|
-
when :min
|
80
|
-
raise InvalidParameterError unless param.nil? || value <= param
|
81
|
-
when :max
|
82
|
-
raise InvalidParameterError unless param.nil? || value >= param
|
83
|
-
when :min_length
|
84
|
-
raise InvalidParameterError unless param.nil? || value <= param.length
|
85
|
-
when :max_length
|
86
|
-
raise InvalidParameterError unless param.nil? || value >= param.length
|
82
|
+
when :min
|
83
|
+
raise InvalidParameterError unless param.nil? || value <= param
|
84
|
+
when :max
|
85
|
+
raise InvalidParameterError unless param.nil? || value >= param
|
86
|
+
when :min_length
|
87
|
+
raise InvalidParameterError unless param.nil? || value <= param.length
|
88
|
+
when :max_length
|
89
|
+
raise InvalidParameterError unless param.nil? || value >= param.length
|
87
90
|
end
|
88
91
|
end
|
89
92
|
end
|
90
|
-
|
93
|
+
|
91
94
|
# ActiveSupport #present? and #blank? without patching Object
|
92
95
|
def present?(object)
|
93
96
|
!blank?(object)
|
94
97
|
end
|
95
|
-
|
98
|
+
|
96
99
|
def blank?(object)
|
97
100
|
object.respond_to?(:empty?) ? object.empty? : !object
|
98
101
|
end
|
99
102
|
end
|
103
|
+
|
100
104
|
helpers Param
|
101
105
|
end
|
data/sinatra-param.gemspec
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
|
3
|
-
require "sinatra/param/version"
|
2
|
+
require File.expand_path('../lib/sinatra/param/version', __FILE__)
|
4
3
|
|
5
4
|
Gem::Specification.new do |s|
|
6
5
|
s.name = "sinatra-param"
|
@@ -11,12 +10,10 @@ Gem::Specification.new do |s|
|
|
11
10
|
s.platform = Gem::Platform::RUBY
|
12
11
|
s.summary = "sinatra-param"
|
13
12
|
s.description = "Parameter Contracts for Sinatra"
|
14
|
-
|
13
|
+
|
15
14
|
s.add_dependency "sinatra", "~> 1.3"
|
16
15
|
|
17
|
-
s.add_development_dependency
|
18
|
-
s.add_development_dependency "rack-test"
|
19
|
-
s.add_development_dependency "rake", "~> 0.9.2"
|
16
|
+
s.add_development_dependency 'simplecov'
|
20
17
|
|
21
18
|
s.files = Dir["./**/*"].reject { |file| file =~ /\.\/(bin|log|pkg|script|spec|test|vendor)/ }
|
22
19
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
data/spec/dummy/app.rb
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'json'
|
3
|
+
require 'time'
|
4
|
+
|
5
|
+
class App < Sinatra::Base
|
6
|
+
helpers Sinatra::Param
|
7
|
+
|
8
|
+
before do
|
9
|
+
content_type :json
|
10
|
+
end
|
11
|
+
|
12
|
+
get '/coerce/string' do
|
13
|
+
params[:arg] = params[:arg].to_i
|
14
|
+
param :arg, String
|
15
|
+
params.to_json
|
16
|
+
end
|
17
|
+
|
18
|
+
get '/coerce/integer' do
|
19
|
+
param :arg, Integer
|
20
|
+
params.to_json
|
21
|
+
end
|
22
|
+
|
23
|
+
get '/coerce/float' do
|
24
|
+
param :arg, Float
|
25
|
+
params.to_json
|
26
|
+
end
|
27
|
+
|
28
|
+
get '/coerce/time' do
|
29
|
+
param :arg, Time
|
30
|
+
params.to_json
|
31
|
+
end
|
32
|
+
|
33
|
+
get '/coerce/date' do
|
34
|
+
param :arg, Date
|
35
|
+
params.to_json
|
36
|
+
end
|
37
|
+
|
38
|
+
get '/coerce/datetime' do
|
39
|
+
param :arg, DateTime
|
40
|
+
params.to_json
|
41
|
+
end
|
42
|
+
|
43
|
+
get '/coerce/array' do
|
44
|
+
param :arg, Array
|
45
|
+
params.to_json
|
46
|
+
end
|
47
|
+
|
48
|
+
get '/coerce/hash' do
|
49
|
+
param :arg, Hash
|
50
|
+
params.to_json
|
51
|
+
end
|
52
|
+
|
53
|
+
get '/coerce/boolean' do
|
54
|
+
param :arg, :boolean
|
55
|
+
params.to_json
|
56
|
+
end
|
57
|
+
|
58
|
+
# transformations
|
59
|
+
get '/default' do
|
60
|
+
param :sort, String, default: "title"
|
61
|
+
params.to_json
|
62
|
+
end
|
63
|
+
|
64
|
+
get '/transform' do
|
65
|
+
param :order, String, transform: :upcase
|
66
|
+
params.to_json
|
67
|
+
end
|
68
|
+
|
69
|
+
# validations
|
70
|
+
get '/validation/required' do
|
71
|
+
param :arg, String, required: true
|
72
|
+
params.to_json
|
73
|
+
end
|
74
|
+
|
75
|
+
get '/validation/blank/string' do
|
76
|
+
param :arg, String, blank: false
|
77
|
+
end
|
78
|
+
|
79
|
+
get '/validation/blank/array' do
|
80
|
+
param :arg, Array, blank: false
|
81
|
+
end
|
82
|
+
|
83
|
+
get '/validation/blank/hash' do
|
84
|
+
param :arg, Hash, blank: false
|
85
|
+
end
|
86
|
+
|
87
|
+
get '/validation/blank/other' do
|
88
|
+
param :arg, Class, blank: false
|
89
|
+
end
|
90
|
+
|
91
|
+
get '/validation/nonblank/string' do
|
92
|
+
param :arg, String, blank: true
|
93
|
+
end
|
94
|
+
|
95
|
+
get '/validation/is' do
|
96
|
+
param :arg, String, is: 'foo'
|
97
|
+
params.to_json
|
98
|
+
end
|
99
|
+
|
100
|
+
get '/validation/in' do
|
101
|
+
param :arg, String, in: ['ASC', 'DESC']
|
102
|
+
params.to_json
|
103
|
+
end
|
104
|
+
|
105
|
+
get '/validation/within' do
|
106
|
+
param :arg, Integer, within: 1..10
|
107
|
+
params.to_json
|
108
|
+
end
|
109
|
+
|
110
|
+
get '/validation/range' do
|
111
|
+
param :arg, Integer, range: 1..10
|
112
|
+
params.to_json
|
113
|
+
end
|
114
|
+
|
115
|
+
get '/validation/min' do
|
116
|
+
param :arg, Integer, min: 12
|
117
|
+
params.to_json
|
118
|
+
end
|
119
|
+
|
120
|
+
get '/validation/max' do
|
121
|
+
param :arg, Integer, max: 20
|
122
|
+
params.to_json
|
123
|
+
end
|
124
|
+
|
125
|
+
get '/validation/min_length' do
|
126
|
+
param :arg, String, min_length: 5
|
127
|
+
params.to_json
|
128
|
+
end
|
129
|
+
|
130
|
+
get '/validation/max_length' do
|
131
|
+
param :arg, String, max_length: 10
|
132
|
+
params.to_json
|
133
|
+
end
|
134
|
+
|
135
|
+
get '/choice' do
|
136
|
+
param :a, String
|
137
|
+
param :b, String
|
138
|
+
param :c, String
|
139
|
+
|
140
|
+
one_of(:a, :b, :c)
|
141
|
+
|
142
|
+
{
|
143
|
+
message: 'OK'
|
144
|
+
}.to_json
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Parameter Sets' do
|
4
|
+
describe 'one_of' do
|
5
|
+
it 'returns 406 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
|
+
params.each do |param|
|
12
|
+
get('/choice', param) do |response|
|
13
|
+
response.status.should == 406
|
14
|
+
JSON.parse(response.body)['message'].should =~ /mutually exclusive/
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'returns successfully for requests that only have one parameter' do
|
20
|
+
params = [
|
21
|
+
{a: 1},
|
22
|
+
{b: 2},
|
23
|
+
{c: 3}
|
24
|
+
]
|
25
|
+
params.each do |param|
|
26
|
+
get('/choice', param) do |response|
|
27
|
+
response.status.should == 200
|
28
|
+
JSON.parse(response.body)['message'].should =~ /OK/
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Parameter Transformations' do
|
4
|
+
describe 'default' do
|
5
|
+
it 'sets a default value when none is given' do
|
6
|
+
get('/default') do |response|
|
7
|
+
response.status.should == 200
|
8
|
+
JSON.parse(response.body)['sort'].should == 'title'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe 'transform' do
|
14
|
+
it 'transforms the input using to_proc' do
|
15
|
+
get('/transform', order: 'asc') do |response|
|
16
|
+
response.status.should == 200
|
17
|
+
JSON.parse(response.body)['order'].should == 'ASC'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Parameter Types' do
|
4
|
+
describe 'String' do
|
5
|
+
it 'coerces strings' do
|
6
|
+
get('/coerce/string', arg: '1234') do |response|
|
7
|
+
response.status.should == 200
|
8
|
+
JSON.parse(response.body)['arg'].should eq('1234')
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe 'Integer' do
|
14
|
+
it 'coerces integers' do
|
15
|
+
get('/coerce/integer', arg: '1234') do |response|
|
16
|
+
response.status.should == 200
|
17
|
+
JSON.parse(response.body)['arg'].should eq(1234)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'Float' do
|
23
|
+
it 'coerces floats' do
|
24
|
+
get('/coerce/float', arg: '1234') do |response|
|
25
|
+
response.status.should == 200
|
26
|
+
JSON.parse(response.body)['arg'].should eq(1234.0)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe 'Time' do
|
32
|
+
it 'coerces time' do
|
33
|
+
get('/coerce/time', arg: '20130117') do |response|
|
34
|
+
response.status.should == 200
|
35
|
+
JSON.parse(response.body)['arg'].should eq('2013-01-17 00:00:00 -0500')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe 'Date' do
|
41
|
+
it 'coerces date' do
|
42
|
+
get('/coerce/date', arg: '20130117') do |response|
|
43
|
+
response.status.should == 200
|
44
|
+
JSON.parse(response.body)['arg'].should eq('2013-01-17')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe 'DateTime' do
|
50
|
+
it 'coerces datetimes' do
|
51
|
+
get('/coerce/datetime', arg: '20130117') do |response|
|
52
|
+
response.status.should == 200
|
53
|
+
JSON.parse(response.body)['arg'].should eq('2013-01-17T00:00:00+00:00')
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe 'Array' do
|
59
|
+
it 'coerces arrays' do
|
60
|
+
get('/coerce/array', arg: '1,2,3,4,5') do |response|
|
61
|
+
response.status.should == 200
|
62
|
+
parsed_body = JSON.parse(response.body)
|
63
|
+
parsed_body['arg'].should be_an(Array)
|
64
|
+
parsed_body['arg'].should eq(%w(1 2 3 4 5))
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe 'Hash' do
|
70
|
+
it 'coerces hashes' do
|
71
|
+
get('/coerce/hash', arg: 'a:b,c:d') do |response|
|
72
|
+
response.status.should == 200
|
73
|
+
parsed_body = JSON.parse(response.body)
|
74
|
+
parsed_body['arg'].should be_an(Hash)
|
75
|
+
parsed_body['arg'].should eq({ 'a' => 'b', 'c' => 'd'})
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe 'Boolean' do
|
81
|
+
it 'coerces truthy booleans to true' do
|
82
|
+
%w(1 true t yes y).each do |bool|
|
83
|
+
get('/coerce/boolean', arg: bool) do |response|
|
84
|
+
response.status.should == 200
|
85
|
+
JSON.parse(response.body)['arg'].should be_true
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|