sinatra-wanted 0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +94 -0
- data/lib/sinatra/helpers/wanted.rb +176 -0
- data/lib/sinatra/helpers/wanted/version.rb +8 -0
- data/sinatra-wanted.gemspec +30 -0
- metadata +95 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2bb6e4a003636fbb934a4b36e249ac757ba1cd450e4d632ea2016b61095d3752
|
4
|
+
data.tar.gz: 6493f6270ae54b97c3df03df9b02146b3a40f43c9e8ca667cdd242033da8232a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f9d6e85a50bd7ac41da1160142ddb6932a00527dea08f57204683506a586792e30ac246c08f64e399e6201678a9e035202c7abaff6a1e1153253923bef6403fb
|
7
|
+
data.tar.gz: 5453e53c9250895bdf081bca06864a06c2fc06771a28a0a05fcf7457ab8eaaeedad933450d5586790246108050684ad6281febe9b498094bda3162c470a4de27
|
data/README.md
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
sinatra-wanted
|
2
|
+
==============
|
3
|
+
|
4
|
+
Parameter processing for Sinatra framework
|
5
|
+
|
6
|
+
Allow to easily expressing parameter requirements, such as:
|
7
|
+
|
8
|
+
* required/optional
|
9
|
+
* type checking/coercion (best done using dry-types)
|
10
|
+
* object retrieval (using Sequel, LOM, or class instantiating)
|
11
|
+
* further processing (such as conversion) using block
|
12
|
+
|
13
|
+
Examples
|
14
|
+
========
|
15
|
+
|
16
|
+
Note that in URL query `?param` as no value but `?param=` as the
|
17
|
+
empty string value (ie: "").
|
18
|
+
|
19
|
+
|
20
|
+
~~~ruby
|
21
|
+
# Retrieve a required VM model from Sequel
|
22
|
+
vm = want! :vm, Types::VM::Name, VM
|
23
|
+
|
24
|
+
# Retrieve a require public key (in rfc4716 or openssh format)
|
25
|
+
# and ensure the final result is in openssh format:
|
26
|
+
pubkey = want! :pubkey, Types::SSHPublicKey do |k|
|
27
|
+
SSHPublicKey.to_openssh(k)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Get an optional parameter called locked which is a boolean,
|
31
|
+
# if the parameter is present but as no value use true
|
32
|
+
locked = want? :locked, Types::Params::Bool.default(true)
|
33
|
+
|
34
|
+
# Parameter is optional but in this case we require a default value
|
35
|
+
# which will be processed
|
36
|
+
type = want :type, Types::VM::Stop, default: 'savestate'
|
37
|
+
~~~
|
38
|
+
|
39
|
+
Parameter processing
|
40
|
+
====================
|
41
|
+
Parameter value retrieval will be processed as follow, please
|
42
|
+
read carefully:
|
43
|
+
|
44
|
+
1. Retrieve parameter value
|
45
|
+
If `param` is a symbol, it's key will be looked up
|
46
|
+
in the sinatra parameter list and assign special value:
|
47
|
+
* nil : key not found
|
48
|
+
* NO_VALUE : key found but no value (ie: nil) associated
|
49
|
+
|
50
|
+
2. Check for missing parameter (ie: nil)
|
51
|
+
According to named-parameter `missing`:
|
52
|
+
* :raise : raise exception WantedMissing
|
53
|
+
* :ignore : use the `default` value and continue processing
|
54
|
+
* :return : return the `default` value (all processing stops here)
|
55
|
+
|
56
|
+
3. Check for missing value (ie: NO_VALUE)
|
57
|
+
* If value is missing use instead the value from the
|
58
|
+
named parameter `no_value` (default to NO_VALUE)
|
59
|
+
* If the type checking/coercion is one of dry-type, the NO_VALUE
|
60
|
+
is changed for the Dry::Types::Undefined so that DRY can
|
61
|
+
correctly processed undefined value.
|
62
|
+
|
63
|
+
4. Perform the type checking / coercion
|
64
|
+
This is done by using the first available method: [], call.
|
65
|
+
|
66
|
+
The easiest (but not required) is to use the dry-types library
|
67
|
+
|
68
|
+
5. Unless value is already nil, use a getter to retrieve the real
|
69
|
+
value object. Object retrieval will be considered as not found,
|
70
|
+
if the getter returns nil
|
71
|
+
This is done by using the first available method: [], get,
|
72
|
+
fetch, call, new.
|
73
|
+
|
74
|
+
Usually getter will be Sequel Model, LDAP Object Model,
|
75
|
+
Class, ...
|
76
|
+
|
77
|
+
If not found (ie: nil), according to named-parameter `not_found`:
|
78
|
+
|
79
|
+
* :raise : raise exception WantedNotFound
|
80
|
+
* :ignore : keep the value as nil and continue processing
|
81
|
+
* :not_found : execute the sinatra #not_found action
|
82
|
+
* :pass : execute the sinatra #pass action
|
83
|
+
|
84
|
+
6. Apply block processing
|
85
|
+
|
86
|
+
\#want, #want!, and #want? are the same methods with different default
|
87
|
+
for the `missing` and `not_found` named parameter
|
88
|
+
|
89
|
+
| method | missing | not_found |
|
90
|
+
|--------|---------|------------|
|
91
|
+
| want | :ignore | :ignore |
|
92
|
+
| want! | :raise | :raise |
|
93
|
+
| want? | :return | :ignore |
|
94
|
+
|
@@ -0,0 +1,176 @@
|
|
1
|
+
require_relative 'wanted/version'
|
2
|
+
|
3
|
+
# {include:file:README.md}
|
4
|
+
|
5
|
+
module Sinatra::Helpers::Wanted
|
6
|
+
# Define a "No Value" object.
|
7
|
+
# It is used to signal that a parameter exists but as no associated value.
|
8
|
+
NO_VALUE = Object.new.then {|o|
|
9
|
+
def o.insect
|
10
|
+
"No_Value"
|
11
|
+
end
|
12
|
+
}.freeze
|
13
|
+
|
14
|
+
# Generic exception.
|
15
|
+
# Only the inherited exceptions are raised.
|
16
|
+
class WantedError < StandardError
|
17
|
+
def initialize(msg=nil, value: nil, id: nil)
|
18
|
+
super(msg)
|
19
|
+
@value = value
|
20
|
+
@id = id
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Exception to notify of syntax error
|
25
|
+
class WantedSyntaxError < WantedError
|
26
|
+
end
|
27
|
+
|
28
|
+
# Exception to notify of missing parameter
|
29
|
+
class WantedMissing < WantedError
|
30
|
+
end
|
31
|
+
|
32
|
+
# Exception to notify of object not found
|
33
|
+
class WantedNotFound < WantedError
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
# Retrieve value/object associated with a parameter.
|
38
|
+
#
|
39
|
+
# @param param [Symbol, Object, nil, NO_VALUE] parameter key or parameter value
|
40
|
+
# @param type [#[], #call] type checking / coercion
|
41
|
+
# @param getter [#[], #get, #fetch, #call, #new] object getter
|
42
|
+
# @param id [Symbol] name of the parameter being processed
|
43
|
+
# @param default [Object] default value to use if parameter is missing
|
44
|
+
# @param no_value [Obejct] default value to use if object is not found
|
45
|
+
# @param missing [:raise, :ignore, :return] how to deal with missing parameter
|
46
|
+
# @param not_found [:false, :ignore, :not_found, :pass] how to deal with object not found
|
47
|
+
#
|
48
|
+
# @yieldparam obj [Object] retrieve parameter value/object
|
49
|
+
# @yieldreturn [Object] modified value/object
|
50
|
+
#
|
51
|
+
# @return [Object] parameter value/object
|
52
|
+
# @return [nil] parameter is missing or it's value is nil
|
53
|
+
# @return [NO_VALUE] parameter has no associated value
|
54
|
+
#
|
55
|
+
# @raise [WantedMissing] parameter is missing
|
56
|
+
# @raise [WantedNotFound] object not found
|
57
|
+
# @raise [WantedSyntaxError] syntax error
|
58
|
+
#
|
59
|
+
def want(param, type=nil, getter=nil, id: nil,
|
60
|
+
default: nil, no_value: NO_VALUE,
|
61
|
+
missing: :ignore, not_found: :ignore, &block)
|
62
|
+
error_handler do
|
63
|
+
_want(param, type, getter, id: id,
|
64
|
+
default: default, no_value: no_value,
|
65
|
+
missing: missing, not_found: not_found, &block)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# (see #want)
|
70
|
+
def want!(param, type=nil, getter=nil, id: nil,
|
71
|
+
default: nil, no_value: NO_VALUE,
|
72
|
+
missing: :raise, not_found: :raise, &block)
|
73
|
+
want(param, type, getter, id: id,
|
74
|
+
default: default, no_value: no_value,
|
75
|
+
missing: missing, not_found: not_found, &block)
|
76
|
+
end
|
77
|
+
|
78
|
+
# (see #want)
|
79
|
+
def want?(param, type=nil, getter=nil, id: nil,
|
80
|
+
default: nil, no_value: NO_VALUE,
|
81
|
+
missing: :return, not_found: :ignore, &block)
|
82
|
+
want(param, type, getter,
|
83
|
+
default: default, id: id, no_value: no_value,
|
84
|
+
missing: missing, not_found: not_found, &block)
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def _want(param, type, getter, id:,
|
91
|
+
default:, no_value:, missing:, not_found:)
|
92
|
+
type_method = if type
|
93
|
+
[ :[], :call ]
|
94
|
+
.find {|m| type.respond_to?(m) } ||
|
95
|
+
raise(ArgumentError)
|
96
|
+
end
|
97
|
+
get_method = if getter
|
98
|
+
[ :[], :get, :fetch, :call, :new ]
|
99
|
+
.find {|m| getter.respond_to?(m) } ||
|
100
|
+
raise(ArgumentError)
|
101
|
+
end
|
102
|
+
value, id = if param.kind_of?(Symbol)
|
103
|
+
if params.include?(param)
|
104
|
+
then [ params[param] || NO_VALUE, param ]
|
105
|
+
else [ nil, param ]
|
106
|
+
end
|
107
|
+
else
|
108
|
+
[ param, nil ]
|
109
|
+
end
|
110
|
+
|
111
|
+
# Check for missing param
|
112
|
+
# Note: we consider the case where `param` is nil to be
|
113
|
+
# a missing parameter, otherwise the user should
|
114
|
+
# have explicitly passed NO_VALUE
|
115
|
+
if value.nil?
|
116
|
+
case missing
|
117
|
+
when :raise then raise WantedMissing, id: id
|
118
|
+
when :return then return default
|
119
|
+
when :ignore then value = default
|
120
|
+
else raise ArgumentError
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# If the parameter has no value, replace it with the
|
125
|
+
# user-supplied no_value
|
126
|
+
# Note: if type is a dry-type, NO_VALUE will be replaced
|
127
|
+
# with Dry::Types::Undefined
|
128
|
+
if value == NO_VALUE
|
129
|
+
value = no_value
|
130
|
+
if value == NO_VALUE &&
|
131
|
+
defined?(Dry::Types) && type.kind_of?(Dry::Types::Type)
|
132
|
+
value = Dry::Types::Undefined
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# Build value from various check/conversion
|
137
|
+
if type_method
|
138
|
+
value = type.public_send(type_method, value)
|
139
|
+
end
|
140
|
+
if !value.nil? && get_method
|
141
|
+
value = getter.public_send(get_method, value)
|
142
|
+
# Check if we consider it as not found
|
143
|
+
if value.nil?
|
144
|
+
case not_found
|
145
|
+
when :raise then raise WantedNotFound, id: id
|
146
|
+
when :not_found then self.not_found
|
147
|
+
when :pass then self.pass
|
148
|
+
when :ignore
|
149
|
+
else raise ArgumentError
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
if block_given?
|
154
|
+
value = yield(value)
|
155
|
+
end
|
156
|
+
|
157
|
+
# Return value
|
158
|
+
value
|
159
|
+
rescue Dry::Types::CoercionError, Dry::Types::ConstraintError
|
160
|
+
raise WantedSyntaxError, value: value, id: id
|
161
|
+
end
|
162
|
+
|
163
|
+
def error_handler
|
164
|
+
if defined?(Dry::Types)
|
165
|
+
begin
|
166
|
+
yield
|
167
|
+
rescue Dry::Types::CoercionError, Dry::Types::ConstraintError
|
168
|
+
raise WantedSyntaxError, value: value, id: id
|
169
|
+
end
|
170
|
+
else
|
171
|
+
yield
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|
176
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require_relative 'lib/sinatra/helpers/wanted/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'sinatra-wanted'
|
7
|
+
s.version = Sinatra::Helpers::Wanted::VERSION
|
8
|
+
s.summary = "Parameters processing for Sinatra framework"
|
9
|
+
s.description = <<~EOF
|
10
|
+
Ease processing of parameters in Sinatra framework.
|
11
|
+
Integrates well with dry-types, sequel, ...
|
12
|
+
|
13
|
+
Example:
|
14
|
+
want! :user, Dry::Types::String, User
|
15
|
+
want? :expired, Dry::Types::Params::Bool.default(true)
|
16
|
+
EOF
|
17
|
+
|
18
|
+
s.homepage = 'https://gitlab.com/sdalu/sinatra-wanted'
|
19
|
+
s.license = 'MIT'
|
20
|
+
|
21
|
+
s.authors = [ "Stéphane D'Alu" ]
|
22
|
+
s.email = [ 'stephane.dalu@insa-lyon.fr' ]
|
23
|
+
|
24
|
+
s.files = %w[ README.md sinatra-wanted.gemspec ] +
|
25
|
+
Dir['lib/**/*.rb']
|
26
|
+
|
27
|
+
s.add_dependency 'sinatra'
|
28
|
+
s.add_development_dependency 'yard', '~>0'
|
29
|
+
s.add_development_dependency 'rake', '~>13'
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sinatra-wanted
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.8'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Stéphane D'Alu
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-05-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: sinatra
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: yard
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '13'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '13'
|
55
|
+
description: |
|
56
|
+
Ease processing of parameters in Sinatra framework.
|
57
|
+
Integrates well with dry-types, sequel, ...
|
58
|
+
|
59
|
+
Example:
|
60
|
+
want! :user, Dry::Types::String, User
|
61
|
+
want? :expired, Dry::Types::Params::Bool.default(true)
|
62
|
+
email:
|
63
|
+
- stephane.dalu@insa-lyon.fr
|
64
|
+
executables: []
|
65
|
+
extensions: []
|
66
|
+
extra_rdoc_files: []
|
67
|
+
files:
|
68
|
+
- README.md
|
69
|
+
- lib/sinatra/helpers/wanted.rb
|
70
|
+
- lib/sinatra/helpers/wanted/version.rb
|
71
|
+
- sinatra-wanted.gemspec
|
72
|
+
homepage: https://gitlab.com/sdalu/sinatra-wanted
|
73
|
+
licenses:
|
74
|
+
- MIT
|
75
|
+
metadata: {}
|
76
|
+
post_install_message:
|
77
|
+
rdoc_options: []
|
78
|
+
require_paths:
|
79
|
+
- lib
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
requirements: []
|
91
|
+
rubygems_version: 3.0.8
|
92
|
+
signing_key:
|
93
|
+
specification_version: 4
|
94
|
+
summary: Parameters processing for Sinatra framework
|
95
|
+
test_files: []
|