sinatra-wanted 0.8

Sign up to get free protection for your applications and to get access to all the features.
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,8 @@
1
+ module Sinatra
2
+ module Helpers
3
+ module Wanted
4
+ # Version
5
+ VERSION = 0.8
6
+ end
7
+ end
8
+ end
@@ -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: []