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 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
-