validate-params 0.7.0 → 0.8.0
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/CHANGELOG.md +5 -0
- data/Gemfile.lock +1 -1
- data/README.md +13 -1
- data/lib/validate_params/param_builder.rb +17 -7
- data/lib/validate_params/param_validator.rb +1 -1
- data/lib/validate_params/types/array.rb +11 -7
- data/lib/validate_params/types/date.rb +1 -1
- data/lib/validate_params/types/date_time.rb +1 -1
- data/lib/validate_params/types/integer.rb +1 -1
- data/lib/validate_params/types/string.rb +1 -1
- data/lib/validate_params/validatable.rb +78 -102
- data/lib/validate_params/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5c5bfbff5338d3dc78e35032adb08de2f63d43e3205cc636e8657c9385ecdc11
|
4
|
+
data.tar.gz: 43d7c4db9adc552528f72de7a7d09ace99a12120860f9fc721ee8476bc201e7f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 508ac950bf308b164b8724bf07687a3473a32b25d4eec3d2cec109bafe5b59eb23454838aa35e1e2a48da3cce011cd0def8168221316e51ec67b1aa595f2ad02
|
7
|
+
data.tar.gz: 36797b8c27c56aea0786cbc4fd9fee79933ff3b5762adc2de6c3a052ed48a380e20f6aa52e1afd9d7bb48988d151aee0af36c2a1ba00f5f04e5cec5121cdfe0f
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.8.0] - 2023-05-30
|
4
|
+
|
5
|
+
- Added support for passing array of actions into validate_params_for to run on multiple actions
|
6
|
+
- Added support for Array type to use option reject_blank: true to remove blank values from array
|
7
|
+
|
3
8
|
## [0.7.0] - 2023-05-30
|
4
9
|
|
5
10
|
- Added type support for casting params into types
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -27,7 +27,7 @@ class TestController < ActionController::Base
|
|
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
29
|
p.param :user_ids, Array, of: Integer, default: [1, 2, 3]
|
30
|
-
p.param :states, Array, of: String, default: ["active", "inactive"]
|
30
|
+
p.param :states, Array, of: String, default: ["active", "inactive"], reject_blank: true
|
31
31
|
p.param :date_of_birth, Hash do |pp|
|
32
32
|
pp.param :gt, Date
|
33
33
|
pp.param :lt, Date
|
@@ -48,6 +48,18 @@ end
|
|
48
48
|
|
49
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.
|
50
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
|
+
|
51
63
|
## Format
|
52
64
|
|
53
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.
|
@@ -3,17 +3,27 @@
|
|
3
3
|
module ValidateParams
|
4
4
|
module Validatable
|
5
5
|
class ParamBuilder
|
6
|
-
def initialize(parent_field
|
6
|
+
def initialize(parent_field: nil, validations:)
|
7
7
|
@parent_field = parent_field
|
8
|
-
@
|
8
|
+
@validations = validations
|
9
9
|
end
|
10
10
|
|
11
|
-
def param(field, type, options = {})
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
11
|
+
def param(field, type, options = {}, &block)
|
12
|
+
if block
|
13
|
+
yield(ParamBuilder.new(parent_field: field, validations: @validations))
|
14
|
+
else
|
15
|
+
@validations << build_config(field, type, options)
|
16
|
+
end
|
16
17
|
end
|
18
|
+
|
19
|
+
private
|
20
|
+
def build_config(field, type, options)
|
21
|
+
if @parent_field.nil?
|
22
|
+
{ field: field, type: type, options: options }
|
23
|
+
else
|
24
|
+
{ field: { @parent_field => field }, type: type, options: options }
|
25
|
+
end
|
26
|
+
end
|
17
27
|
end
|
18
28
|
end
|
19
29
|
end
|
@@ -12,13 +12,17 @@ module ValidateParams
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
def self.cast(raw_value, of: String)
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
15
|
+
def self.cast(raw_value, of: String, reject_blank: false, **)
|
16
|
+
value =
|
17
|
+
case of.to_s
|
18
|
+
when "Integer"
|
19
|
+
raw_value.map { |item| Types::Integer.cast(item) }
|
20
|
+
else
|
21
|
+
raw_value
|
22
|
+
end
|
23
|
+
|
24
|
+
value.reject!(&:blank?) if reject_blank
|
25
|
+
value
|
22
26
|
end
|
23
27
|
end
|
24
28
|
end
|
@@ -14,145 +14,121 @@ module ValidateParams
|
|
14
14
|
extend ::ActiveSupport::Concern
|
15
15
|
|
16
16
|
included do
|
17
|
-
before_action :set_params_defaults
|
18
17
|
before_action :perform_validate_params
|
19
18
|
end
|
20
19
|
|
21
20
|
class_methods do
|
22
|
-
|
21
|
+
attr_reader :params_validations
|
23
22
|
|
24
|
-
def
|
25
|
-
|
23
|
+
def validate_params_for(action, options = {}, &block)
|
24
|
+
options[:format] ||= :json
|
25
|
+
@params_validations ||= {}
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
@params_validations += yield(param_builder)
|
30
|
-
else
|
31
|
-
@params_validations << ParamBuilder.new.param(field, type, options)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def validate_params_for(controller_action, options = {}, &block)
|
36
|
-
@controller_action = controller_action
|
37
|
-
@response_format = options[:format] || :json
|
27
|
+
Array(action).each do |act|
|
28
|
+
@params_validations[act] ||= {options: options, validations: []}
|
38
29
|
|
39
|
-
|
30
|
+
yield(ParamBuilder.new(validations: @params_validations[act][:validations])) if block
|
31
|
+
end
|
40
32
|
end
|
41
33
|
end
|
42
34
|
|
43
35
|
def params_validations
|
44
|
-
self.class.
|
45
|
-
end
|
46
|
-
|
47
|
-
def controller_action
|
48
|
-
self.class.instance_variable_get(:@controller_action) || nil
|
49
|
-
end
|
50
|
-
|
51
|
-
def response_format
|
52
|
-
self.class.instance_variable_get(:@response_format) || nil
|
36
|
+
self.class.params_validations || {}
|
53
37
|
end
|
54
38
|
|
55
39
|
private
|
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 params[key].is_a? Hash
|
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
|
-
params.deep_merge!(key => { params_validation[:field][key] => value })
|
72
|
-
end
|
73
|
-
else
|
74
|
-
value = if params_validation[:options][:default].is_a?(Proc)
|
75
|
-
params_validation[:options][:default].call
|
76
|
-
else
|
77
|
-
params_validation[:options][:default]
|
78
|
-
end
|
79
|
-
|
80
|
-
params[params_validation[:field]] ||= value
|
81
|
-
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
def cast_param_values
|
87
|
-
params_validations.each do |params_validation|
|
88
|
-
if params_validation[:field].is_a?(Hash)
|
89
|
-
params_validation[:field].each_key do |key|
|
90
|
-
next unless params[key].is_a?(Hash)
|
91
|
-
|
92
|
-
value = params.dig(key, params_validation[:field][key])
|
93
|
-
next if value.blank?
|
94
|
-
|
95
|
-
params.deep_merge!(
|
96
|
-
key => {
|
97
|
-
params_validation[:field][key] => if params_validation[:type].name == "Array"
|
98
|
-
Types.const_get(params_validation[:type].name).cast(value,
|
99
|
-
of: params_validation[:options][:of])
|
100
|
-
else
|
101
|
-
Types.const_get(params_validation[:type].name).cast(value)
|
102
|
-
end
|
103
|
-
}
|
104
|
-
)
|
105
|
-
end
|
106
|
-
else
|
107
|
-
value = params[params_validation[:field]]
|
108
|
-
next if value.blank?
|
109
|
-
|
110
|
-
params[params_validation[:field]] = if params_validation[:type].name == "Array"
|
111
|
-
Types.const_get(params_validation[:type].name).cast(value, of: params_validation[:options][:of])
|
112
|
-
else
|
113
|
-
Types.const_get(params_validation[:type].name).cast(value)
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
40
|
def perform_validate_params
|
120
|
-
return unless
|
41
|
+
return unless params_validations.key?(action_name.to_sym)
|
121
42
|
|
122
43
|
errors = []
|
44
|
+
config = params_validations[action_name.to_sym]
|
123
45
|
|
124
|
-
|
125
|
-
|
126
|
-
next if params_validation[:field].is_a?(Hash) &&
|
127
|
-
params[params_validation[:field].keys.first].is_a?(String)
|
46
|
+
config[:validations].each do |validation|
|
47
|
+
apply_default_values(validation)
|
128
48
|
|
129
|
-
|
130
|
-
|
131
|
-
|
49
|
+
next if validation[:field].is_a?(Hash) &&
|
50
|
+
params[validation[:field].keys.first].is_a?(String)
|
51
|
+
|
52
|
+
parameter_value = if validation[:field].is_a? Hash
|
53
|
+
params.dig(validation[:field].keys.first,
|
54
|
+
validation[:field][validation[:field].keys.first])
|
132
55
|
else
|
133
|
-
params[
|
56
|
+
params[validation[:field]]
|
134
57
|
end
|
135
58
|
|
136
59
|
ParamValidator.call(
|
137
|
-
type:
|
138
|
-
field:
|
60
|
+
type: validation[:type],
|
61
|
+
field: validation[:field],
|
139
62
|
value: parameter_value,
|
140
63
|
errors: errors,
|
141
|
-
options:
|
64
|
+
options: validation[:options]
|
142
65
|
)
|
143
66
|
end
|
144
67
|
|
145
68
|
if errors.empty?
|
146
|
-
cast_param_values
|
69
|
+
cast_param_values(config[:validations])
|
147
70
|
return
|
148
71
|
end
|
149
72
|
|
150
|
-
case
|
73
|
+
case config.dig(:options, :format)
|
151
74
|
when :html
|
152
75
|
head :bad_request
|
153
76
|
else
|
154
77
|
render json: { success: false, errors: errors }, status: :bad_request
|
155
78
|
end
|
156
79
|
end
|
80
|
+
|
81
|
+
def apply_default_values(validation)
|
82
|
+
return unless validation[:options].key?(:default)
|
83
|
+
|
84
|
+
if validation[:field].is_a?(Hash)
|
85
|
+
validation[:field].each_key do |key|
|
86
|
+
# Skip in case hash is configured and string is passed
|
87
|
+
next if hashlike?(params[key])
|
88
|
+
next if params.dig(key, validation[:field][key])
|
89
|
+
|
90
|
+
value = if validation[:options][:default].is_a?(Proc)
|
91
|
+
validation[:options][:default].call
|
92
|
+
else
|
93
|
+
validation[:options][:default]
|
94
|
+
end
|
95
|
+
|
96
|
+
params[key] ||= {}
|
97
|
+
params[key][validation[:field][key]] = value
|
98
|
+
end
|
99
|
+
else
|
100
|
+
value = if validation[:options][:default].is_a?(Proc)
|
101
|
+
validation[:options][:default].call
|
102
|
+
else
|
103
|
+
validation[:options][:default]
|
104
|
+
end
|
105
|
+
|
106
|
+
params[validation[:field]] ||= value
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def cast_param_values(validations)
|
111
|
+
validations.each do |validation|
|
112
|
+
if validation[:field].is_a?(Hash)
|
113
|
+
validation[:field].each_key do |key|
|
114
|
+
next unless hashlike?(params[key])
|
115
|
+
|
116
|
+
value = params.dig(key, validation[:field][key])
|
117
|
+
next if value.blank?
|
118
|
+
|
119
|
+
params[key][validation[:field][key]] = Types.const_get(validation[:type].name).cast(value, **validation.fetch(:options, {}))
|
120
|
+
end
|
121
|
+
else
|
122
|
+
value = params[validation[:field]]
|
123
|
+
next if value.blank?
|
124
|
+
|
125
|
+
params[validation[:field]] = Types.const_get(validation[:type].name).cast(value, **validation.fetch(:options, {}))
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def hashlike?(obj)
|
131
|
+
obj.is_a?(Hash) || obj.is_a?(ActionController::Parameters)
|
132
|
+
end
|
157
133
|
end
|
158
134
|
end
|