sinatra-browse 0.2 → 0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: eb3a18b58acc57c6a80b56bf6a0e08d96e2b04e0
4
- data.tar.gz: 87150a5f51798b69ac97540940caec5ba16a5f9d
3
+ metadata.gz: 582bf7da2ddf0b18a42136d6fb4c52b8bf929f46
4
+ data.tar.gz: 4c37bf5a4830a81b5c11c5c4cf4f3f95e17f8252
5
5
  SHA512:
6
- metadata.gz: 64b8e196681b25a346f8f0cfe135e220a9ebd1b38da76c50481491be880e9817d2384b293e588da7f4155bb0f7131cff9cef974516146bc230452775b8c285e7
7
- data.tar.gz: 004f30d10ea627e10adce8b34a2115c820ff2b0934bbc3af47bb2a9d3116e154d04fd2d92a6d671047aaa4961674e42adf636e194706072d03c43581b8a431bf
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 404, "if you're not giving us a number between 1 and 9, we're going to pretend not to be here!" }
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
- ## Parameter transformation
121
+ ### The error hash
113
122
 
114
- You can use transform to execute a quick method on any prameter provided. Anything that will respond to *to_proc* will do.
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 :only_caps, :String, transform: :upcase
118
- param :power_of_two, :Integer, transform: proc { |n| n * n }
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
- disable :remove_undefined_parameters
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 can also set a `system_parameters` variable to allow for a select few parameters that aren't removed. By default this is set to *[ "splat", "captures" ]*.
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
- set system_parameters: [ "id", "username", "password" ]
199
+ Some exta discussion of this problem can be found [here](https://github.com/sinatra/sinatra/issues/417).
@@ -53,17 +53,17 @@
53
53
  }
54
54
  end
55
55
 
56
- def delete_undefined(params, system_params)
57
- params.delete_if { |i| !(self.has_parameter?(i) || system_params.member?(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
- { success: false, reason: reason }.merge parameter
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)
@@ -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 system_parameters: ["splat", "captures"]
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.system_parameters)
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
- instance_exec &validation_result[:on_error].to_proc
90
+ error_proc = validation_result.delete(:on_error).to_proc
91
+ instance_exec validation_result, &error_proc
72
92
  else
73
- halt 400, {
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.2'
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
-