wsdsl 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +23 -0
- data/README.md +100 -0
- data/Rakefile +35 -0
- data/VERSION +1 -0
- data/lib/documentation.rb +151 -0
- data/lib/framework_ext/sinatra.rb +30 -0
- data/lib/framework_ext/sinatra_controller.rb +80 -0
- data/lib/inflection.rb +479 -0
- data/lib/params.rb +366 -0
- data/lib/params_verification.rb +222 -0
- data/lib/response.rb +301 -0
- data/lib/ws_list.rb +29 -0
- data/lib/wsdsl.rb +332 -0
- data/spec/hello_world_controller.rb +5 -0
- data/spec/hello_world_service.rb +20 -0
- data/spec/params_verification_spec.rb +61 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/test_services.rb +70 -0
- data/spec/wsdsl_sinatra_ext_spec.rb +26 -0
- data/spec/wsdsl_spec.rb +190 -0
- data/wsdsl.gemspec +67 -0
- metadata +91 -0
data/lib/params.rb
ADDED
@@ -0,0 +1,366 @@
|
|
1
|
+
class WSDSL
|
2
|
+
# Service params class letting you define param rules.
|
3
|
+
# Usually not initialized directly but accessed via the service methods.
|
4
|
+
#
|
5
|
+
# @see WSDSL#params
|
6
|
+
#
|
7
|
+
# @api public
|
8
|
+
class Params
|
9
|
+
|
10
|
+
# Params usually have a few rules used to validate requests.
|
11
|
+
# Rules are not usually initialized directly but instead via
|
12
|
+
# the service's #params accessor.
|
13
|
+
#
|
14
|
+
# @api public
|
15
|
+
class Rule
|
16
|
+
|
17
|
+
# @return [Symbol, String] name The name of the param the rule applies to.
|
18
|
+
# @api public
|
19
|
+
attr_reader :name
|
20
|
+
|
21
|
+
# @return [Hash] options The rule options.
|
22
|
+
# @option options [Symbol] :in A list of acceptable values.
|
23
|
+
# @option options [Symbol] :options A list of acceptable values.
|
24
|
+
# @option options [Symbol] :default The default value of the param.
|
25
|
+
# @option options [Symbol] :minvalue The minimum acceptable value.
|
26
|
+
# @option options [Symbol] :maxvalue The maximim acceptable value.
|
27
|
+
# @api public
|
28
|
+
attr_reader :options
|
29
|
+
|
30
|
+
|
31
|
+
# @param [Symbol, String] name
|
32
|
+
# The param's name
|
33
|
+
# @param [Hash] opts The rule options
|
34
|
+
# @option opts [Symbol] :in A list of acceptable values.
|
35
|
+
# @option opts [Symbol] :options A list of acceptable values.
|
36
|
+
# @option opts [Symbol] :default The default value of the param.
|
37
|
+
# @option opts [Symbol] :minvalue The minimum acceptable value.
|
38
|
+
# @option opts [Symbol] :maxvalue The maximim acceptable value.
|
39
|
+
# @api public
|
40
|
+
def initialize(name, opts = {})
|
41
|
+
@name = name
|
42
|
+
@options = opts
|
43
|
+
end
|
44
|
+
|
45
|
+
# The namespace used if any
|
46
|
+
#
|
47
|
+
# @return [NilClass, String]
|
48
|
+
# @api public
|
49
|
+
def namespace
|
50
|
+
@options[:space_name]
|
51
|
+
end
|
52
|
+
|
53
|
+
end # of Rule
|
54
|
+
|
55
|
+
# The namespace used if any
|
56
|
+
#
|
57
|
+
# @return [String]
|
58
|
+
# @api public
|
59
|
+
attr_reader :space_name
|
60
|
+
|
61
|
+
# @param [Hash] opts The params options
|
62
|
+
# @option opts [:symbol] :space_name Optional namespace.
|
63
|
+
# @api public
|
64
|
+
def initialize(opts={})
|
65
|
+
@space_name = opts[:space_name]
|
66
|
+
end
|
67
|
+
|
68
|
+
# Defines a new param and add it to the optional or required list based
|
69
|
+
# the passed options.
|
70
|
+
#
|
71
|
+
# @param [Symbol, String] name
|
72
|
+
# The name of the param
|
73
|
+
# @param [Symbol] type
|
74
|
+
# The type of param
|
75
|
+
# @param [Hash] options
|
76
|
+
# A hash representing the param settings
|
77
|
+
#
|
78
|
+
# @example Declaring an integer service param called id
|
79
|
+
# service.param(:id, :integer, :default => 9999, :in => [0, 9999])
|
80
|
+
#
|
81
|
+
# @return [Array] the typed list of params (required or optional)
|
82
|
+
# @api public]
|
83
|
+
def param(name, type, options={})
|
84
|
+
options[:type] = type
|
85
|
+
options[:space_name] = options[:space_name] || space_name
|
86
|
+
if options.delete(:required)
|
87
|
+
list_required << Rule.new(name, options)
|
88
|
+
else
|
89
|
+
list_optional << Rule.new(name, options)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# @group Params defintition DSL (accept_param style)
|
94
|
+
|
95
|
+
# Defines a new string param and add it to the required or optional list
|
96
|
+
#
|
97
|
+
# @param [String] name
|
98
|
+
# The name of the param
|
99
|
+
# @param [Hash] options
|
100
|
+
# A hash representing the param settings
|
101
|
+
#
|
102
|
+
# @example Defining a string service param named type which has various options.
|
103
|
+
# service.param.string :type, :in => LeaderboardType.names, :default => LeaderboardType::LIFETIME
|
104
|
+
#
|
105
|
+
# @api public
|
106
|
+
# @return [Arrays<WSDSL::Params::Rule>]
|
107
|
+
# List of optional or required param rules depending on the new param rule type
|
108
|
+
def string(name, options={})
|
109
|
+
param(name, :string, options)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Defines a new integer param and add it to the required or optional list
|
113
|
+
#
|
114
|
+
# @param [String] name
|
115
|
+
# The name of the param
|
116
|
+
# @param [Hash] options
|
117
|
+
# A hash representing the param settings
|
118
|
+
#
|
119
|
+
# @example Defining a string service param named type which has various options.
|
120
|
+
# service.param.string :type, :in => LeaderboardType.names, :default => LeaderboardType::LIFETIME
|
121
|
+
#
|
122
|
+
# @api public
|
123
|
+
# @return [Arrays<WSDSL::Params::Rule>]
|
124
|
+
# List of optional or required param rules depending on the new param rule type
|
125
|
+
def integer(name, options={})
|
126
|
+
param(name, :integer, options)
|
127
|
+
end
|
128
|
+
|
129
|
+
# Defines a new float param and add it to the required or optional list
|
130
|
+
#
|
131
|
+
# @param [String] name
|
132
|
+
# The name of the param
|
133
|
+
# @param [Hash] options
|
134
|
+
# A hash representing the param settings
|
135
|
+
#
|
136
|
+
# @example Defining a string service param named type which has various options.
|
137
|
+
# service.param.string :type, :in => LeaderboardType.names, :default => LeaderboardType::LIFETIME
|
138
|
+
#
|
139
|
+
# @api public
|
140
|
+
# @return [Arrays<WSDSL::Params::Rule>]
|
141
|
+
# List of optional or required param rules depending on the new param rule type
|
142
|
+
def float(name, options={})
|
143
|
+
param(name, :float, options)
|
144
|
+
end
|
145
|
+
|
146
|
+
# Defines a new decimal param and add it to the required or optional list
|
147
|
+
#
|
148
|
+
# @param [String] name
|
149
|
+
# The name of the param
|
150
|
+
# @param [Hash] options
|
151
|
+
# A hash representing the param settings
|
152
|
+
#
|
153
|
+
# @example Defining a string service param named type which has various options.
|
154
|
+
# service.param.string :type, :in => LeaderboardType.names, :default => LeaderboardType::LIFETIME
|
155
|
+
#
|
156
|
+
# @api public
|
157
|
+
# @return [Arrays<WSDSL::Params::Rule>]
|
158
|
+
# List of optional or required param rules depending on the new param rule type
|
159
|
+
def decimal(name, options={})
|
160
|
+
param(name, :decimal, options)
|
161
|
+
end
|
162
|
+
|
163
|
+
# Defines a new boolean param and add it to the required or optional list
|
164
|
+
#
|
165
|
+
# @param [String] name
|
166
|
+
# The name of the param
|
167
|
+
# @param [Hash] options
|
168
|
+
# A hash representing the param settings
|
169
|
+
#
|
170
|
+
# @example Defining a string service param named type which has various options.
|
171
|
+
# service.param.string :type, :in => LeaderboardType.names, :default => LeaderboardType::LIFETIME
|
172
|
+
#
|
173
|
+
# @api public
|
174
|
+
# @return [Arrays<WSDSL::Params::Rule>]
|
175
|
+
# List of optional or required param rules depending on the new param rule type
|
176
|
+
def boolean(name, options={})
|
177
|
+
param(name, :boolean, options)
|
178
|
+
end
|
179
|
+
|
180
|
+
# Defines a new datetime param and add it to the required or optional list
|
181
|
+
#
|
182
|
+
# @param [String] name
|
183
|
+
# The name of the param
|
184
|
+
# @param [Hash] options
|
185
|
+
# A hash representing the param settings
|
186
|
+
#
|
187
|
+
# @example Defining a string service param named type which has various options.
|
188
|
+
# service.param.string :type, :in => LeaderboardType.names, :default => LeaderboardType::LIFETIME
|
189
|
+
#
|
190
|
+
# @api public
|
191
|
+
# @return [Arrays<WSDSL::Params::Rule>]
|
192
|
+
# List of optional or required param rules depending on the new param rule type
|
193
|
+
def datetime(name, options={})
|
194
|
+
param(name, :datetime, options)
|
195
|
+
end
|
196
|
+
|
197
|
+
# Defines a new text param and add it to the required or optional list
|
198
|
+
#
|
199
|
+
# @param [String] name
|
200
|
+
# The name of the param
|
201
|
+
# @param [Hash] options
|
202
|
+
# A hash representing the param settings
|
203
|
+
#
|
204
|
+
# @example Defining a string service param named type which has various options.
|
205
|
+
# service.param.string :type, :in => LeaderboardType.names, :default => LeaderboardType::LIFETIME
|
206
|
+
#
|
207
|
+
# @api public
|
208
|
+
# @return [Arrays<WSDSL::Params::Rule>]
|
209
|
+
# List of optional or required param rules depending on the new param rule type
|
210
|
+
def text(name, options={})
|
211
|
+
param(name, :text, options)
|
212
|
+
end
|
213
|
+
|
214
|
+
# Defines a new binary param and add it to the required or optional list
|
215
|
+
#
|
216
|
+
# @param [String] name
|
217
|
+
# The name of the param
|
218
|
+
# @param [Hash] options
|
219
|
+
# A hash representing the param settings
|
220
|
+
#
|
221
|
+
# @example Defining a string service param named type which has various options.
|
222
|
+
# service.param.string :type, :in => LeaderboardType.names, :default => LeaderboardType::LIFETIME
|
223
|
+
#
|
224
|
+
# @api public
|
225
|
+
# @return [Arrays<WSDSL::Params::Rule>]
|
226
|
+
# List of optional or required param rules depending on the new param rule type
|
227
|
+
def binary(name, options={})
|
228
|
+
param(name, :binary, options)
|
229
|
+
end
|
230
|
+
|
231
|
+
# Defines a new array param and add it to the required or optional list
|
232
|
+
#
|
233
|
+
# @param [String] name
|
234
|
+
# The name of the param
|
235
|
+
# @param [Hash] options
|
236
|
+
# A hash representing the param settings
|
237
|
+
#
|
238
|
+
# @example Defining a string service param named type which has various options.
|
239
|
+
# service.param.string :type, :in => LeaderboardType.names, :default => LeaderboardType::LIFETIME
|
240
|
+
#
|
241
|
+
# @api public
|
242
|
+
# @return [Array<WSDSL::Params::Rule>]
|
243
|
+
# List of optional or required param rules depending on the new param rule type
|
244
|
+
def array(name, options={})
|
245
|
+
param(name, :array, options)
|
246
|
+
end
|
247
|
+
|
248
|
+
# Defines a new file param and add it to the required or optional list
|
249
|
+
#
|
250
|
+
# @param [String] name
|
251
|
+
# The name of the param
|
252
|
+
# @param [Hash] options
|
253
|
+
# A hash representing the param settings
|
254
|
+
#
|
255
|
+
# @example Defining a string service param named type which has various options.
|
256
|
+
# service.param.string :type, :in => LeaderboardType.names, :default => LeaderboardType::LIFETIME
|
257
|
+
#
|
258
|
+
# @api public
|
259
|
+
# @return [Arrays<WSDSL::Params::Rule>]
|
260
|
+
# List of optional or required param rules depending on the new param rule type
|
261
|
+
def file(name, options={})
|
262
|
+
param(name, :file, options)
|
263
|
+
end
|
264
|
+
|
265
|
+
# @group param setters based on the state (required or optional)
|
266
|
+
|
267
|
+
# Defines a new required param
|
268
|
+
#
|
269
|
+
# @param [Symbol, String] param_name
|
270
|
+
# The name of the param to define
|
271
|
+
# @param [Hash] opts
|
272
|
+
# A hash representing the required param, the key being the param name name
|
273
|
+
# and the value being a hash of options.
|
274
|
+
#
|
275
|
+
# @example Defining a required service param called 'id' of `Integer` type
|
276
|
+
# service.params.required :id, :type => 'integer', :default => 9999
|
277
|
+
#
|
278
|
+
# @return [Array<WSDSL::Params::Rule>] The list of required rules
|
279
|
+
#
|
280
|
+
# @api public
|
281
|
+
def required(param_name, opts={})
|
282
|
+
# # support for when a required param doesn't have any options
|
283
|
+
# unless opts.respond_to?(:each_pair)
|
284
|
+
# opts = {opts => nil}
|
285
|
+
# end
|
286
|
+
# # recursive rule creation
|
287
|
+
# if opts.size > 1
|
288
|
+
# opts.each_pair{|k,v| requires({k => v})}
|
289
|
+
# else
|
290
|
+
list_required << Rule.new(param_name, opts)
|
291
|
+
# end
|
292
|
+
end
|
293
|
+
|
294
|
+
# Defines a new optional param rule
|
295
|
+
#
|
296
|
+
# @param [Symbol, String] param_name
|
297
|
+
# The name of the param to define
|
298
|
+
# @param [Hash] opts
|
299
|
+
# A hash representing the required param, the key being the param name name
|
300
|
+
# and the value being a hash of options.
|
301
|
+
#
|
302
|
+
# @example Defining an optional service param called 'id' of `Integer` type
|
303
|
+
# service.params.optional :id, :type => 'integer', :default => 9999
|
304
|
+
#
|
305
|
+
# @return [Array<WSDSL::Params::Rule>] The list of optional rules
|
306
|
+
# @api public
|
307
|
+
def optional(param_name, opts={})
|
308
|
+
# # recursive rule creation
|
309
|
+
# if opts.size > 1
|
310
|
+
# opts.each_pair{|k,v| optional({k => v})}
|
311
|
+
# else
|
312
|
+
list_optional << Rule.new(param_name, opts)
|
313
|
+
# end
|
314
|
+
end
|
315
|
+
|
316
|
+
# @group params accessors per status (required or optional)
|
317
|
+
|
318
|
+
# Returns an array of all the required params
|
319
|
+
#
|
320
|
+
# @return [Array<WSDSL::Params::Rule>] The list of required rules
|
321
|
+
# @api public
|
322
|
+
def list_required
|
323
|
+
@required ||= []
|
324
|
+
end
|
325
|
+
|
326
|
+
# Returns an array of all the optional params
|
327
|
+
#
|
328
|
+
# @return [Array<WSDSL::Params::Rule>] all the optional params
|
329
|
+
# @api public
|
330
|
+
def list_optional
|
331
|
+
@optional ||= []
|
332
|
+
end
|
333
|
+
|
334
|
+
# @endgroup
|
335
|
+
|
336
|
+
# Defines a namespaced param
|
337
|
+
#
|
338
|
+
# @yield [Params] the newly created namespaced param
|
339
|
+
# @return [Array<WSDSL::Params>] the list of all the namespaced params
|
340
|
+
# @api public
|
341
|
+
def namespace(name)
|
342
|
+
params = Params.new(:space_name => name)
|
343
|
+
yield(params) if block_given?
|
344
|
+
namespaced_params << params unless namespaced_params.include?(params)
|
345
|
+
end
|
346
|
+
|
347
|
+
# Returns the namespaced params
|
348
|
+
#
|
349
|
+
# @return [Array<WSDSL::Params>] the list of all the namespaced params
|
350
|
+
# @api public
|
351
|
+
def namespaced_params
|
352
|
+
@namespaced_params ||= []
|
353
|
+
end
|
354
|
+
|
355
|
+
# Returns the names of the first level expected params
|
356
|
+
#
|
357
|
+
# @return [Array<WSDSL::Params>]
|
358
|
+
# @api public
|
359
|
+
def param_names
|
360
|
+
first_level_expected_params = (list_required + list_optional).map{|rule| rule.name.to_s}
|
361
|
+
first_level_expected_params += namespaced_params.map{|r| r.space_name.to_s}
|
362
|
+
first_level_expected_params
|
363
|
+
end
|
364
|
+
|
365
|
+
end # of Params
|
366
|
+
end
|
@@ -0,0 +1,222 @@
|
|
1
|
+
# ParamsVerification module.
|
2
|
+
# Written to verify a service params without creating new objects.
|
3
|
+
# This module is used on all requests requiring validation and therefore performance
|
4
|
+
# security and maintainability are critical.
|
5
|
+
#
|
6
|
+
# @api public
|
7
|
+
module ParamsVerification
|
8
|
+
|
9
|
+
class ParamError < StandardError; end #:nodoc
|
10
|
+
class NoParamsDefined < ParamError; end #:nodoc
|
11
|
+
class MissingParam < ParamError; end #:nodoc
|
12
|
+
class UnexpectedParam < ParamError; end #:nodoc
|
13
|
+
class InvalidParamType < ParamError; end #:nodoc
|
14
|
+
class InvalidParamValue < ParamError; end #:nodoc
|
15
|
+
|
16
|
+
# An array of validation regular expressions.
|
17
|
+
# The array gets cached but can be accessed via the symbol key.
|
18
|
+
#
|
19
|
+
# @return [Hash] An array with all the validation types as keys and regexps as values.
|
20
|
+
# @api public
|
21
|
+
def self.type_validations
|
22
|
+
@type_validations ||= { :integer => /^-?\d+$/,
|
23
|
+
:float => /^-?(\d*\.\d+|\d+)$/,
|
24
|
+
:decimal => /^-?(\d*\.\d+|\d+)$/,
|
25
|
+
:datetime => /^[-\d:T\s]+$/, # "T" is for ISO date format
|
26
|
+
:boolean => /^(1|true|TRUE|T|Y|0|false|FALSE|F|N)$/
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
# Validation against each required WSDSL::Params::Rule
|
31
|
+
# and returns the potentially modified params (with default values)
|
32
|
+
#
|
33
|
+
# @param [Hash] params The params to verify (incoming request params)
|
34
|
+
# @param [WSDSL::Params] service_params A Playco service param compatible object listing required and optional params
|
35
|
+
# @param [Boolean] ignore_unexpected Flag letting the validation know if unexpected params should be ignored
|
36
|
+
#
|
37
|
+
# @return [Hash]
|
38
|
+
# The passed params potentially modified by the default rules defined in the service.
|
39
|
+
#
|
40
|
+
# @example Validate request params against a service's defined param rules
|
41
|
+
# ParamsVerification.validate!(request.params, @service.defined_params)
|
42
|
+
#
|
43
|
+
# @api public
|
44
|
+
def self.validate!(params, service_params, ignore_unexpected=false)
|
45
|
+
|
46
|
+
# Verify that no garbage params are passed, if they are, an exception is raised.
|
47
|
+
# only the first level is checked at this point
|
48
|
+
unless ignore_unexpected
|
49
|
+
unexpected_params?(params, service_params.param_names)
|
50
|
+
end
|
51
|
+
|
52
|
+
# dupe the params so we don't modify the passed value
|
53
|
+
updated_params = params.dup
|
54
|
+
# Required param verification
|
55
|
+
service_params.list_required.each do |rule|
|
56
|
+
updated_params = validate_required_rule(rule, updated_params)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Set optional defaults if any optional
|
60
|
+
service_params.list_optional.each do |rule|
|
61
|
+
updated_params = run_optional_rule(rule, updated_params)
|
62
|
+
end
|
63
|
+
|
64
|
+
# check the namespaced params
|
65
|
+
service_params.namespaced_params.each do |param|
|
66
|
+
param.list_required.each do |rule|
|
67
|
+
updated_params = validate_required_rule(rule, updated_params, param.space_name.to_s)
|
68
|
+
end
|
69
|
+
# TODO add verification for namespaced optional rules
|
70
|
+
end
|
71
|
+
|
72
|
+
# verify nested params, only 1 level deep tho
|
73
|
+
params.each_pair do |key, value|
|
74
|
+
if value.is_a?(Hash)
|
75
|
+
namespaced = service_params.namespaced_params.find{|np| np.space_name.to_s == key.to_s}
|
76
|
+
raise UnexpectedParam, "Request included unexpected parameter: #{key}" if namespaced.nil?
|
77
|
+
unexpected_params?(params[key], namespaced.param_names)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
updated_params
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
# Validate a required rule against a list of params passed.
|
88
|
+
#
|
89
|
+
#
|
90
|
+
# @param [WSDSL::Params::Rule] rule The required rule to check against.
|
91
|
+
# @param [Hash] params The request params.
|
92
|
+
# @param [String] namespace Optional param namespace to check the rule against.
|
93
|
+
#
|
94
|
+
# @return [Hash]
|
95
|
+
# A hash representing the potentially modified params after going through the filter.
|
96
|
+
#
|
97
|
+
# @api private
|
98
|
+
def self.validate_required_rule(rule, params, namespace=nil)
|
99
|
+
param_name = rule.name.to_s
|
100
|
+
|
101
|
+
# Namespace check
|
102
|
+
if namespace == '' || namespace.nil?
|
103
|
+
param_value = params[param_name]
|
104
|
+
else
|
105
|
+
# puts "namespace: #{namespace} - params #{params[namespace].inspect}"
|
106
|
+
namespaced_params = params[namespace]
|
107
|
+
param_value = namespaced_params ? namespaced_params[param_name] : nil
|
108
|
+
end
|
109
|
+
# puts "verify #{param_name} params, current value: #{param_value}"
|
110
|
+
|
111
|
+
# Checks default
|
112
|
+
if param_value.nil? && rule.options && rule.options[:default]
|
113
|
+
param_ref = namespace.nil? ? params[param_name] : params[namespace][param_name]
|
114
|
+
param_ref = rule.options[:default]
|
115
|
+
# Checks presence
|
116
|
+
elsif !(namespaced_params || params).keys.include?(param_name)
|
117
|
+
raise MissingParam, "'#{rule.name}' is missing - passed params: #{params.inspect}."
|
118
|
+
# checks null
|
119
|
+
elsif param_value.nil? && !rule.options[:null]
|
120
|
+
raise InvalidParamValue, "Value for parameter '#{param_name}' is missing - passed params: #{params.inspect}."
|
121
|
+
# checks type
|
122
|
+
elsif rule.options[:type]
|
123
|
+
verify_cast(param_name, param_value, rule.options[:type])
|
124
|
+
elsif rule.options[:options] || rule.options[:in]
|
125
|
+
choices = rule.options[:options] || rule.options[:in]
|
126
|
+
if rule.options[:type]
|
127
|
+
# Force the cast so we can compare properly
|
128
|
+
param_value = params[param_name] = type_cast_value(rule.options[:type], param_value)
|
129
|
+
end
|
130
|
+
raise InvalidParamValue, "Value for parameter '#{param_name}' (#{param_value}) is not in the allowed set of values." unless choices.include?(param_value)
|
131
|
+
elsif rule.options[:minvalue]
|
132
|
+
min = rule.options[:minvalue]
|
133
|
+
raise InvalidParamValue, "Value for parameter '#{param_name}' is lower than the min accepted value (#{min})." if param_value.to_i >= min
|
134
|
+
end
|
135
|
+
# Returns the updated params
|
136
|
+
|
137
|
+
# cast the type if a type is defined and if a range of options isn't defined since the casting should have been done already
|
138
|
+
if rule.options[:type] && !(rule.options[:options] || rule.options[:in])
|
139
|
+
# puts "casting #{param_value} into type: #{rule.options[:type]}"
|
140
|
+
params[param_name] = type_cast_value(rule.options[:type], param_value)
|
141
|
+
end
|
142
|
+
|
143
|
+
params
|
144
|
+
end
|
145
|
+
|
146
|
+
# @todo add support for namespaces
|
147
|
+
# @param [#WSDSL::Params::Rule] rule The optional rule
|
148
|
+
# @param [Hash] params The request params
|
149
|
+
# @param [String] namespace An optional namespace
|
150
|
+
# @return [Hash] The potentially modified params
|
151
|
+
# @api private
|
152
|
+
def self.run_optional_rule(rule, params, namespace=nil)
|
153
|
+
param_name = rule.name.to_s
|
154
|
+
param_value = params[param_name]
|
155
|
+
if param_value.nil? && rule.options[:default]
|
156
|
+
params[param_name] = rule.options[:default]
|
157
|
+
end
|
158
|
+
|
159
|
+
# cast the type if a type is defined and if a range of options isn't defined since the casting should have been done already
|
160
|
+
if rule.options[:type] && !param_value.nil?
|
161
|
+
params[param_name] = type_cast_value(rule.options[:type], param_value)
|
162
|
+
end
|
163
|
+
|
164
|
+
params
|
165
|
+
end
|
166
|
+
|
167
|
+
def self.unexpected_params?(params, param_names)
|
168
|
+
# Raise an exception unless no unexpected params were found
|
169
|
+
unexpected_keys = (params.keys(&:to_s) - param_names)
|
170
|
+
unless unexpected_keys.empty?
|
171
|
+
raise UnexpectedParam, "Request included unexpected parameter(s): #{unexpected_keys.join(', ')}"
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
|
176
|
+
def self.type_cast_value(type, value)
|
177
|
+
case type
|
178
|
+
when :integer
|
179
|
+
value.to_i
|
180
|
+
when :float, :decimal
|
181
|
+
value.to_f
|
182
|
+
when :string
|
183
|
+
value.to_s
|
184
|
+
when :boolean
|
185
|
+
if value.is_a? TrueClass
|
186
|
+
true
|
187
|
+
elsif value.is_a? FalseClass
|
188
|
+
false
|
189
|
+
else
|
190
|
+
case value.to_s
|
191
|
+
when /^(1|true|TRUE|T|Y)$/
|
192
|
+
true
|
193
|
+
when /^(0|false|FALSE|F|N)$/
|
194
|
+
false
|
195
|
+
else
|
196
|
+
raise InvalidParamValue, "Could not typecast boolean to appropriate value"
|
197
|
+
end
|
198
|
+
end
|
199
|
+
when :binary, :array, :file
|
200
|
+
value
|
201
|
+
else
|
202
|
+
value
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
# Checks that the value's type matches the expected type for a given param
|
207
|
+
#
|
208
|
+
# @param [Symbol, String] Param name used if the verification fails and that an error is raised.
|
209
|
+
# @param [#to_s] The value to validate.
|
210
|
+
# @param [Symbol] The expected type, such as :boolean, :integer etc...
|
211
|
+
# @raise [InvalidParamType] Custom exception raised when the validation isn't found or the value doesn't match.
|
212
|
+
#
|
213
|
+
# @return [Nil]
|
214
|
+
# @api public
|
215
|
+
def self.verify_cast(name, value, expected_type)
|
216
|
+
validation = ParamsVerification.type_validations[expected_type.to_sym]
|
217
|
+
unless validation.nil? || value.to_s =~ validation
|
218
|
+
raise InvalidParamType, "Value for parameter '#{name}' (#{value}) is of the wrong type (expected #{expected_type})"
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
end
|