validate-params 0.6.1 → 0.7.1
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 +4 -4
- data/.rubocop.yml +356 -4
- data/CHANGELOG.md +5 -0
- data/Gemfile.lock +2 -1
- data/README.md +14 -0
- data/docker-compose.yml +12 -0
- data/lib/validate_params/param_builder.rb +19 -0
- data/lib/validate_params/param_validator.rb +92 -0
- data/lib/validate_params/types/array.rb +25 -0
- data/lib/validate_params/types/date.rb +32 -19
- data/lib/validate_params/types/date_time.rb +11 -1
- data/lib/validate_params/types/integer.rb +15 -10
- data/lib/validate_params/types/string.rb +11 -0
- data/lib/validate_params/validatable.rb +78 -116
- data/lib/validate_params/version.rb +1 -1
- data/lib/validate_params.rb +2 -2
- data/validate_params.gemspec +1 -0
- metadata +21 -3
- data/lib/validate_params/validators/date.rb +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c8a3bd014c84bdbaf778f5fc1e3c5b1e666fcf1ff9ab95107b509defffb42dd8
|
4
|
+
data.tar.gz: e2e3a30f811d7551df3f863ca54c5347f6f3c8c729e494d3649e67b71580e8ea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 45b0c42c93eea9f538c52a1fd90df22d6b0dab828eec6f6be89359f8f52d4c287507547247c5f05c4859099c4dab73b04085a269c44972190fa5b2ab12235d0f
|
7
|
+
data.tar.gz: 86250638fe0a6963d71ee7b6842cd754f95ddccff639e5caed9f6acdc4eeb1caaed13d3ccedfc361220b6afc755cc005942cf98f3ca5809e27e86d29a1d31b94
|
data/.rubocop.yml
CHANGED
@@ -1,13 +1,365 @@
|
|
1
1
|
AllCops:
|
2
|
-
TargetRubyVersion: 2.7
|
2
|
+
TargetRubyVersion: 2.7.0
|
3
3
|
|
4
|
+
# https://edgeguides.rubyonrails.org/contributing_to_ruby_on_rails.html#follow-the-coding-conventions
|
5
|
+
|
6
|
+
# No blank line after access modifiers
|
7
|
+
Layout/EmptyLinesAroundAccessModifier:
|
8
|
+
EnforcedStyle: only_before
|
9
|
+
|
10
|
+
# Hard to use with WSL2
|
11
|
+
Layout/EndOfLine:
|
12
|
+
Enabled: false
|
13
|
+
|
14
|
+
# First element shall always be relative to the first position of the line where the opening bracket is
|
15
|
+
Layout/FirstArrayElementIndentation:
|
16
|
+
EnforcedStyle: consistent
|
17
|
+
|
18
|
+
# First key shall always be relative to the first position of the line where the opening brace is
|
19
|
+
Layout/FirstHashElementIndentation:
|
20
|
+
EnforcedStyle: consistent
|
21
|
+
|
22
|
+
# Table-like left alignment of keys, hash rockets, and values
|
23
|
+
Layout/HashAlignment:
|
24
|
+
EnforcedHashRocketStyle: table
|
25
|
+
|
26
|
+
# Method definitions after access modifiers isolated calls need one extra level of indentation
|
27
|
+
Layout/IndentationConsistency:
|
28
|
+
EnforcedStyle: indented_internal_methods
|
29
|
+
|
30
|
+
# The second operand should be indented is binary operations that span more than one line
|
31
|
+
Layout/MultilineOperationIndentation:
|
32
|
+
EnforcedStyle: indented
|
33
|
+
|
34
|
+
# Braces around single line blocks, do..end around multi-line blocks, except for multi-line blocks
|
35
|
+
# whose return value is being chained with another method
|
36
|
+
Style/BlockDelimiters:
|
37
|
+
EnforcedStyle: braces_for_chaining
|
38
|
+
|
39
|
+
# Enforce the block end operator to go on its own line in empty methods
|
40
|
+
Style/EmptyMethod:
|
41
|
+
EnforcedStyle: expanded
|
42
|
+
|
43
|
+
# Enforce absence of braces around hash literal as a last array item
|
44
|
+
Style/HashAsLastArrayItem:
|
45
|
+
EnforcedStyle: no_braces
|
46
|
+
|
47
|
+
# Use double quotes for string literals
|
4
48
|
Style/StringLiterals:
|
5
|
-
Enabled: true
|
6
49
|
EnforcedStyle: double_quotes
|
7
50
|
|
51
|
+
# Use double quotes inside expressions in interpolated strings
|
8
52
|
Style/StringLiteralsInInterpolation:
|
9
|
-
Enabled: true
|
10
53
|
EnforcedStyle: double_quotes
|
11
54
|
|
55
|
+
# Use %w or %W for arrays of words whose element count is greater than or equal to 5
|
56
|
+
Style/WordArray:
|
57
|
+
MinSize: 5
|
58
|
+
|
59
|
+
Style/BlockComments:
|
60
|
+
Enabled: false
|
61
|
+
|
62
|
+
Style/ClassAndModuleChildren:
|
63
|
+
Enabled: false
|
64
|
+
|
65
|
+
Style/Documentation:
|
66
|
+
Enabled: false
|
67
|
+
|
68
|
+
Style/HashSyntax:
|
69
|
+
EnforcedShorthandSyntax: never
|
70
|
+
|
71
|
+
Style/FrozenStringLiteralComment:
|
72
|
+
Enabled: false
|
73
|
+
|
74
|
+
Bundler/OrderedGems:
|
75
|
+
Enabled: false
|
76
|
+
|
77
|
+
Metrics/AbcSize:
|
78
|
+
Enabled: false
|
79
|
+
|
80
|
+
Metrics/BlockLength:
|
81
|
+
Enabled: false
|
82
|
+
|
83
|
+
Metrics/BlockNesting:
|
84
|
+
Enabled: false
|
85
|
+
|
86
|
+
Metrics/ClassLength:
|
87
|
+
Enabled: false
|
88
|
+
|
89
|
+
Metrics/CyclomaticComplexity:
|
90
|
+
Enabled: false
|
91
|
+
|
92
|
+
Metrics/MethodLength:
|
93
|
+
Enabled: false
|
94
|
+
|
95
|
+
Metrics/ModuleLength:
|
96
|
+
Enabled: false
|
97
|
+
|
98
|
+
Metrics/ParameterLists:
|
99
|
+
Enabled: false
|
100
|
+
|
101
|
+
Metrics/PerceivedComplexity:
|
102
|
+
Enabled: false
|
103
|
+
|
104
|
+
# ┌──────────────────────────────────────────────────────────┐
|
105
|
+
# │TODO: Consider refactoring and applying the following cops│
|
106
|
+
# └──────────────────────────────────────────────────────────┘
|
107
|
+
|
108
|
+
Style/ClassVars:
|
109
|
+
Enabled: false
|
110
|
+
|
111
|
+
Style/CombinableLoops:
|
112
|
+
Enabled: false
|
113
|
+
|
114
|
+
Style/For:
|
115
|
+
Enabled: false
|
116
|
+
|
117
|
+
Style/FloatDivision:
|
118
|
+
Enabled: false
|
119
|
+
|
120
|
+
Style/GlobalVars:
|
121
|
+
Enabled: false
|
122
|
+
|
123
|
+
Style/GuardClause:
|
124
|
+
Enabled: false
|
125
|
+
|
126
|
+
Style/HashLikeCase:
|
127
|
+
Enabled: false
|
128
|
+
|
129
|
+
Style/IdenticalConditionalBranches:
|
130
|
+
Enabled: false
|
131
|
+
|
132
|
+
Style/IfUnlessModifier:
|
133
|
+
Enabled: false
|
134
|
+
|
135
|
+
Style/InfiniteLoop:
|
136
|
+
Enabled: false
|
137
|
+
|
138
|
+
Style/InverseMethods:
|
139
|
+
Enabled: false
|
140
|
+
|
141
|
+
Style/KeywordParametersOrder:
|
142
|
+
Enabled: false
|
143
|
+
|
144
|
+
Style/Lambda:
|
145
|
+
Enabled: false
|
146
|
+
|
147
|
+
Style/LineEndConcatenation:
|
148
|
+
Enabled: false
|
149
|
+
|
150
|
+
Style/MixinUsage:
|
151
|
+
Enabled: false
|
152
|
+
|
153
|
+
Style/NegatedIf:
|
154
|
+
Enabled: false
|
155
|
+
|
156
|
+
Style/Next:
|
157
|
+
Enabled: false
|
158
|
+
|
159
|
+
Style/Not:
|
160
|
+
Enabled: false
|
161
|
+
|
162
|
+
Style/NumericLiterals:
|
163
|
+
Enabled: false
|
164
|
+
|
165
|
+
Style/MultilineBlockChain:
|
166
|
+
Enabled: false
|
167
|
+
|
168
|
+
Style/MultilineIfModifier:
|
169
|
+
Enabled: false
|
170
|
+
|
171
|
+
Style/MultipleComparison:
|
172
|
+
Enabled: false
|
173
|
+
|
174
|
+
Style/MultilineTernaryOperator:
|
175
|
+
Enabled: false
|
176
|
+
|
177
|
+
Style/MutableConstant:
|
178
|
+
Enabled: false
|
179
|
+
|
180
|
+
Style/NestedParenthesizedCalls:
|
181
|
+
Enabled: false
|
182
|
+
|
183
|
+
Style/NestedTernaryOperator:
|
184
|
+
Enabled: false
|
185
|
+
|
186
|
+
Style/NumericLiteralPrefix:
|
187
|
+
Enabled: false
|
188
|
+
|
189
|
+
Style/NumericPredicate:
|
190
|
+
Enabled: false
|
191
|
+
|
192
|
+
Style/OptionalBooleanParameter:
|
193
|
+
Enabled: false
|
194
|
+
|
195
|
+
Style/OrAssignment:
|
196
|
+
Enabled: false
|
197
|
+
|
198
|
+
Style/PerlBackrefs:
|
199
|
+
Enabled: false
|
200
|
+
|
201
|
+
Style/PreferredHashMethods:
|
202
|
+
Enabled: false
|
203
|
+
|
204
|
+
Style/RaiseArgs:
|
205
|
+
Enabled: false
|
206
|
+
|
207
|
+
Style/RedundantAssignment:
|
208
|
+
Enabled: false
|
209
|
+
|
210
|
+
Style/RedundantFetchBlock:
|
211
|
+
Enabled: false
|
212
|
+
|
213
|
+
Style/RedundantInterpolation:
|
214
|
+
Enabled: false
|
215
|
+
|
216
|
+
Style/RedundantRegexpEscape:
|
217
|
+
Enabled: false
|
218
|
+
|
219
|
+
Style/RedundantSelf:
|
220
|
+
Enabled: false
|
221
|
+
|
222
|
+
Style/RegexpLiteral:
|
223
|
+
Enabled: false
|
224
|
+
|
225
|
+
Style/RescueModifier:
|
226
|
+
Enabled: false
|
227
|
+
|
228
|
+
Style/RescueStandardError:
|
229
|
+
Enabled: false
|
230
|
+
|
231
|
+
Style/SafeNavigation:
|
232
|
+
Enabled: false
|
233
|
+
|
234
|
+
Style/SignalException:
|
235
|
+
Enabled: false
|
236
|
+
|
237
|
+
Style/SlicingWithRange:
|
238
|
+
Enabled: false
|
239
|
+
|
240
|
+
Style/SoleNestedConditional:
|
241
|
+
Enabled: false
|
242
|
+
|
243
|
+
Style/StringConcatenation:
|
244
|
+
Enabled: false
|
245
|
+
|
246
|
+
Style/StructInheritance:
|
247
|
+
Enabled: false
|
248
|
+
|
249
|
+
Style/SymbolArray:
|
250
|
+
Enabled: false
|
251
|
+
|
252
|
+
Style/SymbolProc:
|
253
|
+
Enabled: false
|
254
|
+
|
255
|
+
Style/UnlessElse:
|
256
|
+
Enabled: true
|
257
|
+
|
258
|
+
Style/WhileUntilDo:
|
259
|
+
Enabled: false
|
260
|
+
|
261
|
+
Style/WhileUntilModifier:
|
262
|
+
Enabled: false
|
263
|
+
|
264
|
+
Lint/AssignmentInCondition:
|
265
|
+
Enabled: false
|
266
|
+
|
267
|
+
Lint/BinaryOperatorWithIdenticalOperands:
|
268
|
+
Enabled: false
|
269
|
+
|
270
|
+
Lint/BooleanSymbol:
|
271
|
+
Enabled: false
|
272
|
+
|
273
|
+
Lint/CircularArgumentReference:
|
274
|
+
Enabled: false
|
275
|
+
|
276
|
+
Lint/DisjunctiveAssignmentInConstructor:
|
277
|
+
Enabled: false
|
278
|
+
|
279
|
+
Lint/DuplicateMethods:
|
280
|
+
Enabled: false
|
281
|
+
|
282
|
+
Lint/EmptyConditionalBody:
|
283
|
+
Enabled: false
|
284
|
+
|
285
|
+
Lint/EmptyWhen:
|
286
|
+
Enabled: false
|
287
|
+
|
288
|
+
Style/IfInsideElse:
|
289
|
+
Enabled: false
|
290
|
+
|
291
|
+
Lint/IneffectiveAccessModifier:
|
292
|
+
Enabled: false
|
293
|
+
|
294
|
+
Lint/MissingSuper:
|
295
|
+
Enabled: false
|
296
|
+
|
297
|
+
Lint/NestedMethodDefinition:
|
298
|
+
Enabled: false
|
299
|
+
|
300
|
+
Lint/NonDeterministicRequireOrder:
|
301
|
+
Enabled: false
|
302
|
+
|
303
|
+
Lint/ParenthesesAsGroupedExpression:
|
304
|
+
Enabled: false
|
305
|
+
|
306
|
+
Lint/RedundantWithIndex:
|
307
|
+
Enabled: false
|
308
|
+
|
309
|
+
Lint/RequireParentheses:
|
310
|
+
Enabled: false
|
311
|
+
|
312
|
+
Lint/RescueException:
|
313
|
+
Enabled: false
|
314
|
+
|
315
|
+
Lint/ShadowedArgument:
|
316
|
+
Enabled: false
|
317
|
+
|
318
|
+
Lint/SuppressedException:
|
319
|
+
Enabled: false
|
320
|
+
|
321
|
+
Lint/ToJSON:
|
322
|
+
Enabled: false
|
323
|
+
|
324
|
+
Lint/UnusedBlockArgument:
|
325
|
+
Enabled: false
|
326
|
+
|
327
|
+
Lint/UnusedMethodArgument:
|
328
|
+
Enabled: false
|
329
|
+
|
330
|
+
Lint/UriRegexp:
|
331
|
+
Enabled: false
|
332
|
+
|
333
|
+
Lint/UselessAccessModifier:
|
334
|
+
Enabled: false
|
335
|
+
|
12
336
|
Layout/LineLength:
|
13
|
-
|
337
|
+
Enabled: false
|
338
|
+
|
339
|
+
Naming/AccessorMethodName:
|
340
|
+
Enabled: false
|
341
|
+
|
342
|
+
Naming/MemoizedInstanceVariableName:
|
343
|
+
Enabled: false
|
344
|
+
|
345
|
+
Naming/MethodParameterName:
|
346
|
+
Enabled: false
|
347
|
+
|
348
|
+
Naming/PredicateName:
|
349
|
+
Enabled: false
|
350
|
+
|
351
|
+
Naming/VariableNumber:
|
352
|
+
Enabled: false
|
353
|
+
|
354
|
+
# ┌──────────────────────────────────────────────────────────┐
|
355
|
+
# │Enabled pending cops. Remove when added to default config │
|
356
|
+
# └──────────────────────────────────────────────────────────┘
|
357
|
+
|
358
|
+
Style/StringChars:
|
359
|
+
Enabled: true
|
360
|
+
|
361
|
+
Style/RedundantInitialize:
|
362
|
+
Enabled: true
|
363
|
+
|
364
|
+
Style/CaseEquality:
|
365
|
+
Enabled: false
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -26,6 +26,8 @@ class TestController < ActionController::Base
|
|
26
26
|
p.param :name, String, default: "John Doe"
|
27
27
|
p.param :occurred_on, Date, required: true, default: proc { Date.today }
|
28
28
|
p.param :quantity, Integer, required: true, in: [1, 2, 3]
|
29
|
+
p.param :user_ids, Array, of: Integer, default: [1, 2, 3]
|
30
|
+
p.param :states, Array, of: String, default: ["active", "inactive"]
|
29
31
|
p.param :date_of_birth, Hash do |pp|
|
30
32
|
pp.param :gt, Date
|
31
33
|
pp.param :lt, Date
|
@@ -46,6 +48,18 @@ end
|
|
46
48
|
|
47
49
|
If the parameters are valid, the controller action will be executed as normal. If the parameters are invalid, a **400 Bad Request** response will be returned with a JSON body containing the errors, or an empty HTML response.
|
48
50
|
|
51
|
+
```json
|
52
|
+
{
|
53
|
+
"success": false,
|
54
|
+
"errors": [
|
55
|
+
{
|
56
|
+
"message": "hired_on must be a valid Date"
|
57
|
+
},
|
58
|
+
|
59
|
+
]
|
60
|
+
}
|
61
|
+
```
|
62
|
+
|
49
63
|
## Format
|
50
64
|
|
51
65
|
By default responses are returned in JSON format. To return responses as an empty HTML response, change the :format options in the validate_params methods to :html.
|
data/docker-compose.yml
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ValidateParams
|
4
|
+
module Validatable
|
5
|
+
class ParamBuilder
|
6
|
+
def initialize(parent_field = nil)
|
7
|
+
@parent_field = parent_field
|
8
|
+
@params_validations = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def param(field, type, options = {})
|
12
|
+
return { field: field, type: type, options: options } if @parent_field.nil?
|
13
|
+
|
14
|
+
@params_validations << { field: { @parent_field => field }, type: type, options: options }
|
15
|
+
@params_validations
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/inflector"
|
4
|
+
|
5
|
+
module ValidateParams
|
6
|
+
module Validatable
|
7
|
+
class ParamValidator
|
8
|
+
def self.call(**args)
|
9
|
+
new(**args).call
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(type:, field:, value:, errors:, options: {})
|
13
|
+
@type = type
|
14
|
+
@field = field
|
15
|
+
@value = value
|
16
|
+
@errors = errors
|
17
|
+
@options = options
|
18
|
+
end
|
19
|
+
|
20
|
+
def call
|
21
|
+
return if @value.blank? && !@options[:required]
|
22
|
+
|
23
|
+
if @value.blank? && @options[:required]
|
24
|
+
@errors << { message: required_error_message }
|
25
|
+
return
|
26
|
+
end
|
27
|
+
|
28
|
+
send(@type.to_s.underscore)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def array
|
33
|
+
return if Types::Array.valid?(@value, of: @options[:of])
|
34
|
+
|
35
|
+
@errors << { message: error_message }
|
36
|
+
end
|
37
|
+
|
38
|
+
def date
|
39
|
+
return if Types::Date.valid?(@value)
|
40
|
+
|
41
|
+
@errors << { message: error_message }
|
42
|
+
end
|
43
|
+
|
44
|
+
def date_time
|
45
|
+
return if Types::DateTime.valid?(@value)
|
46
|
+
|
47
|
+
@errors << { message: error_message }
|
48
|
+
end
|
49
|
+
|
50
|
+
def integer
|
51
|
+
unless Types::Integer.valid?(@value)
|
52
|
+
@errors << { message: error_message }
|
53
|
+
return
|
54
|
+
end
|
55
|
+
|
56
|
+
validate_inclusion if @options[:in].present?
|
57
|
+
end
|
58
|
+
|
59
|
+
def string
|
60
|
+
validate_inclusion if @options[:in].present?
|
61
|
+
end
|
62
|
+
|
63
|
+
def validate_inclusion
|
64
|
+
return if @options[:in].include?(value)
|
65
|
+
|
66
|
+
@errors << {
|
67
|
+
message: I18n.t("validate_params.invalid_in", param: error_param_name),
|
68
|
+
valid_values: @options[:in]
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
def error_param_name
|
73
|
+
case @field
|
74
|
+
when Array
|
75
|
+
"#{@field[0]}[#{@field[1]}]"
|
76
|
+
when Hash
|
77
|
+
@field.map { |k, v| "#{k}[#{v}]" }.first
|
78
|
+
else
|
79
|
+
@field
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def error_message
|
84
|
+
I18n.t("validate_params.invalid_type", param: error_param_name, type: @type)
|
85
|
+
end
|
86
|
+
|
87
|
+
def required_error_message
|
88
|
+
I18n.t("validate_params.required", param: error_param_name)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ValidateParams
|
4
|
+
class Types
|
5
|
+
class Array
|
6
|
+
def self.valid?(value, of: String)
|
7
|
+
case of.to_s
|
8
|
+
when "Integer"
|
9
|
+
value.all? { |item| Types::Integer.valid?(item) }
|
10
|
+
else
|
11
|
+
true
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.cast(raw_value, of: String)
|
16
|
+
case of.to_s
|
17
|
+
when "Integer"
|
18
|
+
raw_value.map { |item| Types::Integer.cast(item) }
|
19
|
+
else
|
20
|
+
raw_value
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -1,19 +1,32 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ValidateParams
|
4
|
+
class Types
|
5
|
+
class Date
|
6
|
+
FORMAT = "%Y-%m-%d"
|
7
|
+
|
8
|
+
def self.valid?(value)
|
9
|
+
value = value.to_s
|
10
|
+
return false unless /\d{4}-\d{2}-\d{2}/.match?(value)
|
11
|
+
|
12
|
+
parsed_date = begin
|
13
|
+
::Date.strptime(value, FORMAT)
|
14
|
+
rescue StandardError
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
return false if parsed_date.nil?
|
18
|
+
return false if parsed_date.year > 9999
|
19
|
+
|
20
|
+
true
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.cast(raw_value, **)
|
24
|
+
return raw_value if raw_value.is_a?(::Date)
|
25
|
+
|
26
|
+
::Date.strptime(raw_value.to_s, FORMAT)
|
27
|
+
rescue StandardError
|
28
|
+
raw_value
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ValidateParams
|
2
4
|
class Types
|
3
5
|
class DateTime
|
@@ -7,6 +9,14 @@ module ValidateParams
|
|
7
9
|
rescue ArgumentError, TypeError
|
8
10
|
false
|
9
11
|
end
|
12
|
+
|
13
|
+
def self.cast(raw_value, **)
|
14
|
+
return raw_value if raw_value.is_a?(::Time)
|
15
|
+
|
16
|
+
Time.at(Integer(raw_value))
|
17
|
+
rescue ArgumentError, TypeError
|
18
|
+
raw_value
|
19
|
+
end
|
10
20
|
end
|
11
21
|
end
|
12
|
-
end
|
22
|
+
end
|
@@ -1,10 +1,15 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ValidateParams
|
4
|
+
class Types
|
5
|
+
class Integer
|
6
|
+
def self.valid?(value)
|
7
|
+
/\A[-+]?\d+\z/ === value.to_s
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.cast(raw_value, **)
|
11
|
+
raw_value.to_i
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -3,6 +3,11 @@
|
|
3
3
|
require "validate_params/types/date"
|
4
4
|
require "validate_params/types/date_time"
|
5
5
|
require "validate_params/types/integer"
|
6
|
+
require "validate_params/types/array"
|
7
|
+
require_relative "param_builder"
|
8
|
+
require_relative "param_validator"
|
9
|
+
|
10
|
+
require "active_support/concern"
|
6
11
|
|
7
12
|
module ValidateParams
|
8
13
|
module Validatable
|
@@ -48,142 +53,99 @@ module ValidateParams
|
|
48
53
|
end
|
49
54
|
|
50
55
|
private
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
def set_params_defaults
|
72
|
-
params_validations.each do |params_validation|
|
73
|
-
next if params_validation[:options][:default].blank?
|
74
|
-
|
75
|
-
if params_validation[:field].is_a?(Hash)
|
76
|
-
params_validation[:field].each_key do |key|
|
77
|
-
# Skip in case hash is configured and string is passed
|
78
|
-
next if params.dig(key).is_a? Hash
|
79
|
-
next if params.dig(key, params_validation[:field][key])
|
80
|
-
|
56
|
+
def set_params_defaults
|
57
|
+
params_validations.each do |params_validation|
|
58
|
+
next unless params_validation[:options].key?(:default)
|
59
|
+
|
60
|
+
if params_validation[:field].is_a?(Hash)
|
61
|
+
params_validation[:field].each_key do |key|
|
62
|
+
# Skip in case hash is configured and string is passed
|
63
|
+
next if hashlike?(params[key])
|
64
|
+
next if params.dig(key, params_validation[:field][key])
|
65
|
+
|
66
|
+
value = if params_validation[:options][:default].is_a?(Proc)
|
67
|
+
params_validation[:options][:default].call
|
68
|
+
else
|
69
|
+
params_validation[:options][:default]
|
70
|
+
end
|
71
|
+
|
72
|
+
params[key] ||= {}
|
73
|
+
params[key][params_validation[:field][key]] = value
|
74
|
+
end
|
75
|
+
else
|
81
76
|
value = if params_validation[:options][:default].is_a?(Proc)
|
82
77
|
params_validation[:options][:default].call
|
83
78
|
else
|
84
79
|
params_validation[:options][:default]
|
85
80
|
end
|
86
|
-
params.merge!(key => { params_validation[:field][key] => value })
|
87
|
-
end
|
88
|
-
else
|
89
|
-
value = if params_validation[:options][:default].is_a?(Proc)
|
90
|
-
params_validation[:options][:default].call
|
91
|
-
else
|
92
|
-
params_validation[:options][:default]
|
93
|
-
end
|
94
81
|
|
95
|
-
|
82
|
+
params[params_validation[:field]] ||= value
|
83
|
+
end
|
96
84
|
end
|
97
85
|
end
|
98
|
-
end
|
99
|
-
|
100
|
-
def perform_validate_params
|
101
|
-
return unless controller_action.present? && controller_action == action_name.to_sym
|
102
|
-
|
103
|
-
errors = []
|
104
86
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
87
|
+
def cast_param_values
|
88
|
+
ActionController::Parameters
|
89
|
+
params_validations.each do |params_validation|
|
90
|
+
if params_validation[:field].is_a?(Hash)
|
91
|
+
params_validation[:field].each_key do |key|
|
92
|
+
next unless hashlike?(params[key])
|
109
93
|
|
110
|
-
|
111
|
-
|
112
|
-
params_validation[:field][params_validation[:field].keys.first])
|
113
|
-
else
|
114
|
-
params[params_validation[:field]]
|
115
|
-
end
|
94
|
+
value = params.dig(key, params_validation[:field][key])
|
95
|
+
next if value.blank?
|
116
96
|
|
117
|
-
|
97
|
+
params[key][params_validation[:field][key]] = Types.const_get(params_validation[:type].name).cast(value, of: params_validation.dig(:options, :of))
|
98
|
+
end
|
99
|
+
else
|
100
|
+
value = params[params_validation[:field]]
|
101
|
+
next if value.blank?
|
118
102
|
|
119
|
-
|
120
|
-
errors << { message: build_required_message(error_param_name(params_validation[:field])) }
|
121
|
-
next
|
122
|
-
end
|
123
|
-
|
124
|
-
case params_validation[:type].to_s
|
125
|
-
when "Date"
|
126
|
-
unless ValidateParams::Types::Date.valid?(parameter_value)
|
127
|
-
errors << {
|
128
|
-
message: build_error_message(error_param_name(params_validation[:field]), params_validation[:type])
|
129
|
-
}
|
130
|
-
end
|
131
|
-
when "DateTime"
|
132
|
-
unless ValidateParams::Types::DateTime.valid?(parameter_value)
|
133
|
-
errors << {
|
134
|
-
message: build_error_message(error_param_name(params_validation[:field]), params_validation[:type])
|
135
|
-
}
|
136
|
-
end
|
137
|
-
when "Integer"
|
138
|
-
unless ValidateParams::Types::Integer.valid?(parameter_value)
|
139
|
-
errors << {
|
140
|
-
message: build_error_message(error_param_name(params_validation[:field]), params_validation[:type])
|
141
|
-
}
|
142
|
-
next
|
143
|
-
end
|
144
|
-
|
145
|
-
parameter_value = parameter_value.to_i
|
146
|
-
if params_validation[:options][:in].present? && !params_validation[:options][:in].include?(parameter_value)
|
147
|
-
errors << {
|
148
|
-
message: I18n.t("validate_params.invalid_in", param: error_param_name(params_validation[:field])),
|
149
|
-
valid_values: params_validation[:options][:in]
|
150
|
-
}
|
151
|
-
end
|
152
|
-
when "String"
|
153
|
-
parameter_value = parameter_value.to_s
|
154
|
-
if params_validation[:options][:in].present? && !params_validation[:options][:in].include?(parameter_value)
|
155
|
-
errors << {
|
156
|
-
message: I18n.t("validate_params.invalid_in", param: error_param_name(params_validation[:field])),
|
157
|
-
valid_values: params_validation[:options][:in]
|
158
|
-
}
|
103
|
+
params[params_validation[:field]] = Types.const_get(params_validation[:type].name).cast(value, of: params_validation.dig(:options, :of))
|
159
104
|
end
|
160
105
|
end
|
161
106
|
end
|
162
107
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
108
|
+
def perform_validate_params
|
109
|
+
return unless controller_action.present? && controller_action == action_name.to_sym
|
110
|
+
|
111
|
+
errors = []
|
112
|
+
|
113
|
+
params_validations.each do |params_validation|
|
114
|
+
# Skip in case hash is configured and string is passed
|
115
|
+
next if params_validation[:field].is_a?(Hash) &&
|
116
|
+
params[params_validation[:field].keys.first].is_a?(String)
|
117
|
+
|
118
|
+
parameter_value = if params_validation[:field].is_a? Hash
|
119
|
+
params.dig(params_validation[:field].keys.first,
|
120
|
+
params_validation[:field][params_validation[:field].keys.first])
|
121
|
+
else
|
122
|
+
params[params_validation[:field]]
|
123
|
+
end
|
124
|
+
|
125
|
+
ParamValidator.call(
|
126
|
+
type: params_validation[:type],
|
127
|
+
field: params_validation[:field],
|
128
|
+
value: parameter_value,
|
129
|
+
errors: errors,
|
130
|
+
options: params_validation[:options]
|
131
|
+
)
|
132
|
+
end
|
172
133
|
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
end
|
134
|
+
if errors.empty?
|
135
|
+
cast_param_values
|
136
|
+
return
|
137
|
+
end
|
178
138
|
|
179
|
-
|
180
|
-
|
181
|
-
|
139
|
+
case response_format
|
140
|
+
when :html
|
141
|
+
head :bad_request
|
142
|
+
else
|
143
|
+
render json: { success: false, errors: errors }, status: :bad_request
|
182
144
|
end
|
145
|
+
end
|
183
146
|
|
184
|
-
|
185
|
-
|
147
|
+
def hashlike?(obj)
|
148
|
+
obj.is_a?(Hash) || obj.is_a?(ActionController::Parameters)
|
186
149
|
end
|
187
|
-
end
|
188
150
|
end
|
189
151
|
end
|
data/lib/validate_params.rb
CHANGED
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
require_relative "validate_params/version"
|
4
4
|
require_relative "validate_params/validatable"
|
5
|
-
|
6
|
-
Dir[File.join(__dir__,
|
5
|
+
|
6
|
+
Dir[File.join(__dir__, "validate_params/types", "*.rb")].sort.each { |file| require file }
|
7
7
|
|
8
8
|
module ValidateParams
|
9
9
|
class Error < StandardError; end
|
data/validate_params.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: validate-params
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- dcherevatenko
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-05-
|
11
|
+
date: 2023-05-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: 6.1.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: i18n
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.6'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.6'
|
83
97
|
description: Provides a clean DSL to validate params for controller actions.
|
84
98
|
email:
|
85
99
|
- 'denis.cherevatenko@peopleforce.io '
|
@@ -95,12 +109,16 @@ files:
|
|
95
109
|
- README.md
|
96
110
|
- Rakefile
|
97
111
|
- config/locales/en.yml
|
112
|
+
- docker-compose.yml
|
98
113
|
- lib/validate_params.rb
|
114
|
+
- lib/validate_params/param_builder.rb
|
115
|
+
- lib/validate_params/param_validator.rb
|
116
|
+
- lib/validate_params/types/array.rb
|
99
117
|
- lib/validate_params/types/date.rb
|
100
118
|
- lib/validate_params/types/date_time.rb
|
101
119
|
- lib/validate_params/types/integer.rb
|
120
|
+
- lib/validate_params/types/string.rb
|
102
121
|
- lib/validate_params/validatable.rb
|
103
|
-
- lib/validate_params/validators/date.rb
|
104
122
|
- lib/validate_params/version.rb
|
105
123
|
- sig/validate_params.rbs
|
106
124
|
- validate_params.gemspec
|
File without changes
|