sinatra-browse 0.2 → 0.3
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/README.md +79 -8
- data/lib/sinatra/browse/route.rb +8 -8
- data/lib/sinatra/browse.rb +26 -9
- metadata +1 -2
- data/lib/sinatra/browse/parameter.rb +0 -49
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 582bf7da2ddf0b18a42136d6fb4c52b8bf929f46
|
4
|
+
data.tar.gz: 4c37bf5a4830a81b5c11c5c4cf4f3f95e17f8252
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9b2bd51af3b6e7532122077dd7496e23695946d5b23d17c061fbeff1be7d5507761a3bca5dd6452febdc993a368fc938bb4248edddd6420ab1090d03abdb725c
|
7
|
+
data.tar.gz: 634102de18bd57e1877dc1672b8e5b1df5d0b2db7172de3041c10b7ef6dea538a24f23390e206f26e4ec31cbdd637bf7b55001e95d3e38b9219124a90835b943
|
data/README.md
CHANGED
@@ -96,12 +96,21 @@ param :order, :String, in: ["ascending", "descending"]
|
|
96
96
|
param :alphanumeric, :String, format: /^[0-9A-Za-z]*$/
|
97
97
|
```
|
98
98
|
|
99
|
+
## Parameter transformation
|
100
|
+
|
101
|
+
You can use transform to execute a quick method on any prameter provided. Anything that responds to *to_proc* will do.
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
param :only_caps, :String, transform: :upcase
|
105
|
+
param :power_of_two, :Integer, transform: proc { |n| n * n }
|
106
|
+
```
|
107
|
+
|
99
108
|
## Error handling
|
100
109
|
|
101
110
|
When a validation fails, a standard 400 error will be returned. You can override this and do your own error handling using `on_error`.
|
102
111
|
|
103
112
|
```ruby
|
104
|
-
param :lets_fail, :Integer, in: 1..9, on_error: proc { halt
|
113
|
+
param :lets_fail, :Integer, in: 1..9, on_error: proc { halt 400, "Must be between 1 and 9!" }
|
105
114
|
get 'example_route' do
|
106
115
|
# This is the scope that the on_error proc will be executed in.
|
107
116
|
end
|
@@ -109,20 +118,82 @@ end
|
|
109
118
|
|
110
119
|
If a request is made that fails validation on the *lets_fail* parameter, then the proc provided to `on_error` will be called **in the same scope as your route**. Therefore you have access to Sinatra keywords such as *halt*.
|
111
120
|
|
112
|
-
|
121
|
+
### The error hash
|
113
122
|
|
114
|
-
|
123
|
+
If you want to write a bit more intricate error handling, you can add *the error hash* as an argument to your `on_error` proc. This hash holds some extra information about what exactly went wrong.
|
115
124
|
|
116
125
|
```ruby
|
117
|
-
param :
|
118
|
-
|
126
|
+
param :lets_fail, :Integer, in: 1..9, required: true, on_error: proc { |error_hash|
|
127
|
+
case error_hash[:reason]
|
128
|
+
when :in
|
129
|
+
halt 400, "Must be between 1 and 9!"
|
130
|
+
when :required
|
131
|
+
halt 400, "Why u no give us lets_fail?"
|
132
|
+
end
|
133
|
+
}
|
134
|
+
get 'example_route' do
|
135
|
+
# Some code
|
136
|
+
end
|
137
|
+
```
|
138
|
+
|
139
|
+
The error hash contains the following keys:
|
140
|
+
|
141
|
+
* `:reason` This tells you what validation failed. Possible values could be `:in`, `:required`, `:format`, etc.
|
142
|
+
* `:parameter` The name of the faulty parameter.
|
143
|
+
* `:value` The value our parameter had which caused it to fail validation.
|
144
|
+
* `:type` The type of our parameter. Could be `:String`, `:Integer`, etc.
|
145
|
+
* Any validation keys that were set in the parameter declaration will also be available in the error hash.
|
146
|
+
|
147
|
+
### Overriding default error behaviour
|
148
|
+
|
149
|
+
So we explained how to do error handling for single parameters. Now what if we wanted to set error handling for the entire application? You can do that with the `default_on_error` method.
|
150
|
+
|
151
|
+
```ruby
|
152
|
+
default_on_error do |error_hash|
|
153
|
+
case error_hash[:reason]
|
154
|
+
when :required
|
155
|
+
halt 400, "#{error_hash[:parameter]} is required! provide it!"
|
156
|
+
else
|
157
|
+
_default_on_error(error_hash)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
param :a, :String, in: ["a"], required: true
|
162
|
+
param :b, :String, format: /^bbb$/
|
163
|
+
get "/features/default_error_override" do
|
164
|
+
# Again this is the scope that default_on_error is executed in
|
165
|
+
params.to_json
|
166
|
+
end
|
119
167
|
```
|
168
|
+
|
169
|
+
The block we passed to the `default_on_error` method will be called or every parameter in our application that fails validation and does not have its own `on_error` block. Notice how inside our `default_on_error`
|
170
|
+
|
171
|
+
You might notice that in our example, the `default_on_error` method makes a call to `_default_on_error`. The latter is a fallback to sinatra-browse's standard error behaviour. It's available form both the `default_on_error` block and procs passed to `on_error` in parameter declarations.
|
172
|
+
|
120
173
|
## Removing undefined parameters
|
121
174
|
|
122
175
|
By default sinatra-browse removes all parameters that weren't defined. You can disable this behaviour with the following line.
|
123
176
|
|
124
|
-
|
177
|
+
```ruby
|
178
|
+
disable :remove_undefined_parameters
|
179
|
+
```
|
180
|
+
|
181
|
+
You can also set a `allowed_undefined_parameters` variable to allow for a select few parameters that aren't removed.
|
182
|
+
|
183
|
+
```ruby
|
184
|
+
set allowed_undefined_parameters: [ "id", "username", "password" ]
|
185
|
+
```
|
186
|
+
|
187
|
+
## Named parameters in route patterns
|
188
|
+
|
189
|
+
Unfortunately you are not able to use Sinatra-browse for named parameters in the route definition. Take the following example.
|
190
|
+
|
191
|
+
```ruby
|
192
|
+
get 'foo/:bar' do
|
193
|
+
# some code
|
194
|
+
end
|
195
|
+
```
|
125
196
|
|
126
|
-
You
|
197
|
+
You will ***not*** be able to define the parameter `bar`. This is because Sinatra-browse does its thing in a before block and these parameters aren't added to the `params` hash until the route itself gets executed.
|
127
198
|
|
128
|
-
|
199
|
+
Some exta discussion of this problem can be found [here](https://github.com/sinatra/sinatra/issues/417).
|
data/lib/sinatra/browse/route.rb
CHANGED
@@ -53,17 +53,17 @@
|
|
53
53
|
}
|
54
54
|
end
|
55
55
|
|
56
|
-
def delete_undefined(params,
|
57
|
-
params.delete_if { |i| !(self.has_parameter?(i) ||
|
56
|
+
def delete_undefined(params, allowed)
|
57
|
+
params.delete_if { |i| !(self.has_parameter?(i) || allowed.member?(i)) }
|
58
58
|
end
|
59
59
|
|
60
60
|
def validate(params)
|
61
61
|
@parameters.each { |k,v|
|
62
|
-
return fail_validation v, :required if !params[k] && v[:required]
|
62
|
+
return fail_validation k, params[k], v, :required if !params[k] && v[:required]
|
63
63
|
if params[k]
|
64
|
-
return fail_validation v, :depends_on if v[:depends_on] && !params[v[:depends_on]]
|
65
|
-
return fail_validation v, :in if v[:in] && !v[:in].member?(params[k])
|
66
|
-
return fail_validation v, :format if v[:type] == :String && v[:format] && !(params[k] =~ v[:format])
|
64
|
+
return fail_validation k, params[k], v, :depends_on if v[:depends_on] && !params[v[:depends_on]]
|
65
|
+
return fail_validation k, params[k], v, :in if v[:in] && !v[:in].member?(params[k])
|
66
|
+
return fail_validation k, params[k], v, :format if v[:type] == :String && v[:format] && !(params[k] =~ v[:format])
|
67
67
|
end
|
68
68
|
}
|
69
69
|
|
@@ -86,8 +86,8 @@
|
|
86
86
|
end
|
87
87
|
end
|
88
88
|
|
89
|
-
def fail_validation(parameter, reason)
|
90
|
-
{
|
89
|
+
def fail_validation(parameter, value, options, reason)
|
90
|
+
{success: false, reason: reason , parameter: parameter, value: value}.merge(options)
|
91
91
|
end
|
92
92
|
|
93
93
|
def build_name(request_method, path_info)
|
data/lib/sinatra/browse.rb
CHANGED
@@ -46,21 +46,40 @@ module Sinatra::Browse
|
|
46
46
|
browse_routes[new_route.name] = new_route
|
47
47
|
end
|
48
48
|
|
49
|
+
def default_on_error(&blk)
|
50
|
+
@default_on_error = blk if block_given?
|
51
|
+
@default_on_error
|
52
|
+
end
|
53
|
+
|
49
54
|
def self.registered(app)
|
50
55
|
@app = app
|
51
56
|
|
52
57
|
app.enable :remove_undefined_parameters
|
53
|
-
app.set
|
58
|
+
app.set allowed_undefined_parameters: []
|
59
|
+
|
60
|
+
app.disable :show_head_routes
|
61
|
+
|
62
|
+
app.class_eval {
|
63
|
+
def _default_on_error(error_hash)
|
64
|
+
halt 400, {
|
65
|
+
error: "parameter validation failed",
|
66
|
+
parameter: error_hash[:parameter],
|
67
|
+
value: error_hash[:value],
|
68
|
+
reason: error_hash[:reason]
|
69
|
+
}.to_json
|
70
|
+
end
|
71
|
+
}
|
72
|
+
|
73
|
+
app.default_on_error { |error_hash| _default_on_error(error_hash) }
|
54
74
|
|
55
75
|
app.before do
|
56
76
|
browse_route = app.browse_routes_for(request.request_method, request.path_info)
|
57
77
|
|
58
78
|
if browse_route
|
59
79
|
#TODO: Optionally throw error for undefined params
|
60
|
-
#TODO: Make undefined parameter deletion optional per route
|
61
80
|
|
62
81
|
if settings.remove_undefined_parameters
|
63
|
-
browse_route.delete_undefined(params, settings.
|
82
|
+
browse_route.delete_undefined(params, settings.allowed_undefined_parameters)
|
64
83
|
end
|
65
84
|
|
66
85
|
browse_route.coerce_type(params)
|
@@ -68,13 +87,10 @@ module Sinatra::Browse
|
|
68
87
|
validation_result = browse_route.validate(params)
|
69
88
|
unless validation_result[:success]
|
70
89
|
if validation_result[:on_error].respond_to?(:to_proc)
|
71
|
-
|
90
|
+
error_proc = validation_result.delete(:on_error).to_proc
|
91
|
+
instance_exec validation_result, &error_proc
|
72
92
|
else
|
73
|
-
|
74
|
-
error: "parameter validation failed",
|
75
|
-
parameter: validation_result[:name],
|
76
|
-
reason: validation_result[:reason]
|
77
|
-
}.to_json
|
93
|
+
instance_exec validation_result, &app.default_on_error
|
78
94
|
end
|
79
95
|
end
|
80
96
|
browse_route.transform(params)
|
@@ -89,6 +105,7 @@ module Sinatra::Browse
|
|
89
105
|
end
|
90
106
|
|
91
107
|
def self.route_added(verb, path, block)
|
108
|
+
return if verb == "HEAD" && !@app.settings.show_head_routes
|
92
109
|
@app.set_browse_routes_for(verb, path)
|
93
110
|
@app.reset_temp_params
|
94
111
|
@app.desc ""
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sinatra-browse
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.3'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Axsh Co. LTD
|
@@ -18,7 +18,6 @@ extra_rdoc_files: []
|
|
18
18
|
files:
|
19
19
|
- lib/sinatra/browse.rb
|
20
20
|
- lib/sinatra/browse/route.rb
|
21
|
-
- lib/sinatra/browse/parameter.rb
|
22
21
|
- lib/sinatra/browse/format.rb
|
23
22
|
- LICENSE
|
24
23
|
- README.md
|
@@ -1,49 +0,0 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
|
3
|
-
module Sinatra::Browse
|
4
|
-
def ValidationError < Exception; end
|
5
|
-
|
6
|
-
class Validation
|
7
|
-
attr_reader :fail_message
|
8
|
-
end
|
9
|
-
|
10
|
-
class In < Validation
|
11
|
-
def fail_message(value, accepted)
|
12
|
-
"Invalid value: '#{value}'. Must be a member of #{accepted.inspect}."
|
13
|
-
end
|
14
|
-
|
15
|
-
def validate(value)
|
16
|
-
end
|
17
|
-
|
18
|
-
def fail(value, accepted)
|
19
|
-
raise ValidationError, fail_message(value, accepted)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
class Parameter
|
24
|
-
attr_reader :value
|
25
|
-
|
26
|
-
def initialize(value)
|
27
|
-
@value = coerce(value)
|
28
|
-
end
|
29
|
-
|
30
|
-
def validate()
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
class BPString < Parameter
|
35
|
-
def coerce(v); String(v) end
|
36
|
-
end
|
37
|
-
|
38
|
-
class BPBoolean < Parameter
|
39
|
-
def coerce(v)
|
40
|
-
case v
|
41
|
-
when "y", "yes", "t", "true", "1"
|
42
|
-
true
|
43
|
-
when "n", "no", "f", "false", "0"
|
44
|
-
false
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|