params_checker 0.2.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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +28 -0
- data/Rakefile +32 -0
- data/app/assets/config/params_checker_manifest.js +1 -0
- data/app/assets/stylesheets/params_checker/application.css +15 -0
- data/app/controllers/params_checker/application_controller.rb +5 -0
- data/app/helpers/params_checker/application_helper.rb +4 -0
- data/app/jobs/params_checker/application_job.rb +4 -0
- data/app/mailers/params_checker/application_mailer.rb +6 -0
- data/app/models/params_checker/application_record.rb +5 -0
- data/app/views/layouts/params_checker/application.html.erb +15 -0
- data/config/routes.rb +2 -0
- data/lib/params_checker/base_params_checker.rb +247 -0
- data/lib/params_checker/engine.rb +7 -0
- data/lib/params_checker/fields.rb +228 -0
- data/lib/params_checker/my_error.rb +9 -0
- data/lib/params_checker/param_checker.rb +291 -0
- data/lib/params_checker/version.rb +3 -0
- data/lib/params_checker.rb +9 -0
- metadata +96 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 0013a86614eb2a40c8e5d526ebba0cdd244367c32e86812f388059e26abaf952
|
4
|
+
data.tar.gz: 675209c8ae0ac1ba49bffd934afa6bb34a66e7c02e107cfbd0718336f362534c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a83330c3e167398a9d90773f568d9666fd4c63fefcae418d3767fc9c868952f09de975435a456ae5a3f7f6c3371a772a2feb64dc3181a3301d119b84fc13260d
|
7
|
+
data.tar.gz: 797e848185371dc8ca275b47fe0d2c92ac8bd1ac05179b1a772eff6b3e3ca7f9145c7dc8b44e294a6d9d897927004f3cb0968465c30ef57877f6269c2e9416d6
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2020
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# ParamsChecker
|
2
|
+
Short description and motivation.
|
3
|
+
|
4
|
+
## Usage
|
5
|
+
How to use my plugin.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
gem 'params_checker'
|
12
|
+
```
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
```bash
|
16
|
+
$ bundle
|
17
|
+
```
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
```bash
|
21
|
+
$ gem 'params_checker', git: 'git@gitlab.com:rexylab/params-checker.git', branch: 'development'
|
22
|
+
```
|
23
|
+
|
24
|
+
## Contributing
|
25
|
+
Contribution directions go here.
|
26
|
+
|
27
|
+
## License
|
28
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'ParamsChecker'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.md')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
|
18
|
+
load 'rails/tasks/engine.rake'
|
19
|
+
|
20
|
+
load 'rails/tasks/statistics.rake'
|
21
|
+
|
22
|
+
require 'bundler/gem_tasks'
|
23
|
+
|
24
|
+
require 'rake/testtask'
|
25
|
+
|
26
|
+
Rake::TestTask.new(:test) do |t|
|
27
|
+
t.libs << 'test'
|
28
|
+
t.pattern = 'test/**/*_test.rb'
|
29
|
+
t.verbose = false
|
30
|
+
end
|
31
|
+
|
32
|
+
task default: :test
|
@@ -0,0 +1 @@
|
|
1
|
+
//= link_directory ../stylesheets/params_checker .css
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
+
* It is generally better to create a new file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
data/config/routes.rb
ADDED
@@ -0,0 +1,247 @@
|
|
1
|
+
module ParamsChecker
|
2
|
+
class BaseParamsChecker
|
3
|
+
include Fields
|
4
|
+
prepend SimpleCommand
|
5
|
+
def initialize(params: {}, context: {}, is_outest_hash: true)
|
6
|
+
@params = params
|
7
|
+
@context = context
|
8
|
+
@is_outest_hash = is_outest_hash
|
9
|
+
@formatted_params_after_default_check = {}
|
10
|
+
@formatted_params_after_custom_specify_field_checks = {}
|
11
|
+
@formatted_params_after_custom_all_fields_check = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.init required: true, many: false, allow_empty: false
|
15
|
+
raise "This field's type must be boolean." if [required, many, allow_empty].any? { |value| !value.in? [true, false] }
|
16
|
+
|
17
|
+
type = many ? 'nested_hashs' : 'nested_hash'
|
18
|
+
{
|
19
|
+
type: type,
|
20
|
+
required: required,
|
21
|
+
many: many,
|
22
|
+
allow_empty: allow_empty,
|
23
|
+
class: self
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def raise_error message="Invalid data"
|
28
|
+
raise MyError.new(message)
|
29
|
+
end
|
30
|
+
|
31
|
+
def call
|
32
|
+
default_check && custom_check
|
33
|
+
error_exist? && add_error
|
34
|
+
formatted_params
|
35
|
+
rescue => e
|
36
|
+
# only add errors at the first hash, else raise error for the first hash to catch
|
37
|
+
# example:
|
38
|
+
# old:
|
39
|
+
# {
|
40
|
+
# "errors": {
|
41
|
+
# "message": "Invalid data",
|
42
|
+
# "details": {
|
43
|
+
# "purchase_order_items": [
|
44
|
+
# {
|
45
|
+
# "errors": {
|
46
|
+
# "message": "Material not exists.",
|
47
|
+
# "details": {}
|
48
|
+
# }
|
49
|
+
# }
|
50
|
+
# ]
|
51
|
+
# }
|
52
|
+
# }
|
53
|
+
# }
|
54
|
+
# new:
|
55
|
+
# {
|
56
|
+
# "errors": {
|
57
|
+
# "message": "Material not exists.",
|
58
|
+
# "details": {}
|
59
|
+
# }
|
60
|
+
# }
|
61
|
+
if e.class.name == 'ParamsChecker::MyError' && is_outest_hash
|
62
|
+
errors.add(:errors, {
|
63
|
+
message: e,
|
64
|
+
details: {}
|
65
|
+
})
|
66
|
+
else
|
67
|
+
raise e
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def error_exist?
|
72
|
+
!errors.empty? && errors.is_a?(Hash)
|
73
|
+
end
|
74
|
+
|
75
|
+
def default_check
|
76
|
+
params_is_a_hash = params.is_a?(ActionController::Parameters) || params.is_a?(Hash)
|
77
|
+
errors.add(:error, "ParamsChecker only receive object or ActionController::Parameters as input.") unless params_is_a_hash
|
78
|
+
params_is_a_hash && all_fields_are_valid
|
79
|
+
end
|
80
|
+
|
81
|
+
def all_fields_are_valid
|
82
|
+
return @all_fields_are_valid if @all_fields_are_valid.present?
|
83
|
+
|
84
|
+
@all_fields_are_valid = true
|
85
|
+
fields.each do |key, value|
|
86
|
+
@all_fields_are_valid = false unless data_valid? key
|
87
|
+
end
|
88
|
+
@all_fields_are_valid
|
89
|
+
end
|
90
|
+
|
91
|
+
def data_valid? key
|
92
|
+
if value_need_to_be_present?(key)
|
93
|
+
if value_present?(key)
|
94
|
+
if value_valid?(key)
|
95
|
+
true
|
96
|
+
else
|
97
|
+
false
|
98
|
+
end
|
99
|
+
else
|
100
|
+
errors.add(key, 'This field is required.')
|
101
|
+
false
|
102
|
+
end
|
103
|
+
else
|
104
|
+
if value_present?(key)
|
105
|
+
if value_valid?(key)
|
106
|
+
true
|
107
|
+
else
|
108
|
+
false
|
109
|
+
end
|
110
|
+
else
|
111
|
+
true
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def value_need_to_be_present? key
|
117
|
+
if fields[key].key?(:default) && !fields[key][:default].nil?
|
118
|
+
@params[key] = fields[key][:default]
|
119
|
+
true
|
120
|
+
else
|
121
|
+
fields[key][:required]
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def value_present? key
|
126
|
+
params.key?(key)
|
127
|
+
end
|
128
|
+
|
129
|
+
def value_valid? key
|
130
|
+
cmd = check_base_on_field_type key
|
131
|
+
if cmd.success?
|
132
|
+
@formatted_params_after_default_check[key] = cmd.result
|
133
|
+
else
|
134
|
+
errors.add(key, cmd.errors[key])
|
135
|
+
end
|
136
|
+
cmd.success?
|
137
|
+
end
|
138
|
+
|
139
|
+
def fields
|
140
|
+
field_params = {}
|
141
|
+
init.each do |key, field|
|
142
|
+
field_params[key] = field
|
143
|
+
end
|
144
|
+
@fields ||= field_params
|
145
|
+
end
|
146
|
+
|
147
|
+
def check_base_on_field_type key
|
148
|
+
case fields[key][:type]
|
149
|
+
when 'num'
|
150
|
+
ParamChecker::NumParamChecker.call key, fields, params
|
151
|
+
when 'int'
|
152
|
+
ParamChecker::IntParamChecker.call key, fields, params
|
153
|
+
when 'char'
|
154
|
+
ParamChecker::CharParamChecker.call key, fields, params
|
155
|
+
when 'text'
|
156
|
+
ParamChecker::CharParamChecker.call key, fields, params
|
157
|
+
when 'arr'
|
158
|
+
ParamChecker::ArrParamChecker.call key, fields, params
|
159
|
+
when 'nested_hash'
|
160
|
+
ParamChecker::NestedHashChecker.call key, fields, params, context
|
161
|
+
when 'nested_hashs'
|
162
|
+
ParamChecker::NestedHashsChecker.call key, fields, params, context
|
163
|
+
when 'date'
|
164
|
+
ParamChecker::DateParamChecker.call key, fields, params
|
165
|
+
when 'time'
|
166
|
+
ParamChecker::TimeParamChecker.call key, fields, params
|
167
|
+
when 'datetime'
|
168
|
+
ParamChecker::DateTimeParamChecker.call key, fields, params
|
169
|
+
when 'email'
|
170
|
+
ParamChecker::EmailParamChecker.call key, fields, params
|
171
|
+
when 'boolean'
|
172
|
+
ParamChecker::BooleanChecker.call key, fields, params
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def custom_check
|
177
|
+
specify_field_checks && all_fields_check
|
178
|
+
end
|
179
|
+
|
180
|
+
def specify_field_checks
|
181
|
+
@formatted_params_after_custom_specify_field_checks = formatted_params_after_default_check
|
182
|
+
fields.each do |key, value|
|
183
|
+
# next unless self.methods.grep(/check_#{key}/).length > 0
|
184
|
+
next unless "check_#{key}".to_sym.in?(self.methods)
|
185
|
+
|
186
|
+
specify_field_check(key)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def specify_field_check(key)
|
191
|
+
check_method = "check_#{key}"
|
192
|
+
total_parameters = method(check_method).arity
|
193
|
+
# check_id(id) or check_id(id, opts)
|
194
|
+
value = total_parameters == 1 ? self.send(check_method, @formatted_params_after_default_check[key])
|
195
|
+
: self.send(check_method, @formatted_params_after_default_check[key], @formatted_params_after_default_check)
|
196
|
+
@formatted_params_after_custom_specify_field_checks.delete(key)
|
197
|
+
@formatted_params_after_custom_specify_field_checks[key] = value
|
198
|
+
end
|
199
|
+
|
200
|
+
def all_fields_check
|
201
|
+
@formatted_params_after_custom_all_fields_check = check formatted_params_after_custom_specify_field_checks
|
202
|
+
end
|
203
|
+
|
204
|
+
def init
|
205
|
+
{}
|
206
|
+
end
|
207
|
+
|
208
|
+
def check params
|
209
|
+
params
|
210
|
+
end
|
211
|
+
|
212
|
+
def formatted_params
|
213
|
+
formatted_params_after_custom_all_fields_check
|
214
|
+
end
|
215
|
+
|
216
|
+
def add_error()
|
217
|
+
# only add errors skeleton at the outest hash
|
218
|
+
return unless is_outest_hash
|
219
|
+
|
220
|
+
details = {}
|
221
|
+
errors.each do |key, value|
|
222
|
+
details[key] = value
|
223
|
+
errors.delete(key)
|
224
|
+
end
|
225
|
+
errors.add(:errors, {
|
226
|
+
message: 'Invalid data',
|
227
|
+
details: details
|
228
|
+
})
|
229
|
+
end
|
230
|
+
|
231
|
+
attr_accessor :params, :context,
|
232
|
+
:formatted_params_after_default_check,
|
233
|
+
:formatted_params_after_custom_specify_field_checks,
|
234
|
+
:formatted_params_after_custom_all_fields_check,
|
235
|
+
:is_outest_hash
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
|
240
|
+
# return true if value_need_to_be_present?(key) && value_present?(key) && value_valid?(key)
|
241
|
+
# return false if value_need_to_be_present?(key) && value_present?(key) && !value_valid?(key)
|
242
|
+
# return false if value_need_to_be_present?(key) && !value_present?(key) && value_valid?(key)
|
243
|
+
# return false if value_need_to_be_present?(key) && !value_present?(key) && !value_valid?(key)
|
244
|
+
# return true if !value_need_to_be_present?(key) && value_present?(key) && value_valid?(key)
|
245
|
+
# return false if !value_need_to_be_present?(key) && value_present?(key) && !value_valid?(key)
|
246
|
+
# return true if !value_need_to_be_present?(key) && !value_present?(key) && value_valid?(key)
|
247
|
+
# return true if !value_need_to_be_present?(key) && !value_present?(key) && !value_valid?(key)
|
@@ -0,0 +1,228 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module ParamsChecker
|
4
|
+
module Fields
|
5
|
+
def text_field(required: true, default: nil, allow_blank: false, min_length: 0, max_length: 30_000, allow_nil: false)
|
6
|
+
raise "This field's type must be integer." if [min_length, max_length].any? { |value| !value.is_a?(Integer) }
|
7
|
+
raise "This field's type must be boolean." if [required, allow_blank, allow_nil].any? { |value| !value.in? [true, false] }
|
8
|
+
raise 'Invalid text length.' unless (min_length >= 0) && (max_length <= 30_000)
|
9
|
+
|
10
|
+
{
|
11
|
+
type: 'char',
|
12
|
+
default: default,
|
13
|
+
allow_blank: allow_blank,
|
14
|
+
required: required,
|
15
|
+
min_length: min_length,
|
16
|
+
max_length: max_length,
|
17
|
+
allow_nil: allow_nil
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
def char_field(required: true, default: nil, allow_blank: false, min_length: 0, max_length: 255, allow_nil: false)
|
22
|
+
raise "This field's type must be integer." if [min_length, max_length].any? { |value| !value.is_a?(Integer) }
|
23
|
+
raise "This field's type must be boolean." if [required, allow_blank, allow_nil].any? { |value| !value.in? [true, false] }
|
24
|
+
raise 'Invalid char length.' unless (min_length >= 0) && (max_length <= 255)
|
25
|
+
|
26
|
+
{
|
27
|
+
type: 'char',
|
28
|
+
default: default,
|
29
|
+
allow_blank: allow_blank,
|
30
|
+
required: required,
|
31
|
+
min_length: min_length,
|
32
|
+
max_length: max_length,
|
33
|
+
allow_nil: allow_nil
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
def bignum_field(required: true, default: nil, min: -2_000_000_000_000, max: 2_000_000_000_000, allow_nil: false)
|
38
|
+
raise "This field's type must be numeric." if [min, max].any? { |value| !value.is_a?(Numeric) }
|
39
|
+
raise "This field's type must be boolean." if [required, allow_nil].any? { |value| !value.in? [true, false] }
|
40
|
+
raise 'Invalid numeric value.' unless (min >= -2_000_000_000_000) && (max <= 2_000_000_000_000)
|
41
|
+
|
42
|
+
{
|
43
|
+
type: 'num',
|
44
|
+
default: default,
|
45
|
+
required: required,
|
46
|
+
min: min,
|
47
|
+
max: max,
|
48
|
+
allow_nil: allow_nil
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
def num_field(required: true, default: nil, min: -2_000_000_000, max: 2_000_000_000, allow_nil: false)
|
53
|
+
raise "This field's type must be numeric." if [min, max].any? { |value| !value.is_a?(Numeric) }
|
54
|
+
raise "This field's type must be boolean." if [required, allow_nil].any? { |value| !value.in? [true, false] }
|
55
|
+
raise 'Invalid numeric value.' unless (min >= -2_000_000_000) && (max <= 2_000_000_000)
|
56
|
+
|
57
|
+
{
|
58
|
+
type: 'num',
|
59
|
+
default: default,
|
60
|
+
required: required,
|
61
|
+
min: min,
|
62
|
+
max: max,
|
63
|
+
allow_nil: allow_nil
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
def bigint_field(required: true, default: nil, min: -2_000_000_000_000, max: 2_000_000_000_000, allow_nil: false)
|
68
|
+
raise "This field's type must be integer." if [min, max].any? { |value| !value.is_a?(Integer) }
|
69
|
+
raise "This field's type must be boolean." if [required, allow_nil].any? { |value| !value.in? [true, false] }
|
70
|
+
raise 'Invalid integer value.' unless (min >= -2_000_000_000_000) && (max <= 2_000_000_000_000)
|
71
|
+
|
72
|
+
{
|
73
|
+
type: 'int',
|
74
|
+
default: default,
|
75
|
+
required: required,
|
76
|
+
min: min,
|
77
|
+
max: max,
|
78
|
+
allow_nil: allow_nil
|
79
|
+
}
|
80
|
+
end
|
81
|
+
|
82
|
+
def int_field(required: true, default: nil, min: -2_000_000_000, max: 2_000_000_000, allow_nil: false)
|
83
|
+
raise "This field's type must be integer." if [min, max].any? { |value| !value.is_a?(Integer) }
|
84
|
+
raise "This field's type must be boolean." if [required, allow_nil].any? { |value| !value.in? [true, false] }
|
85
|
+
raise 'Invalid integer value.' unless (min >= -2_000_000_000) && (max <= 2_000_000_000)
|
86
|
+
|
87
|
+
{
|
88
|
+
type: 'int',
|
89
|
+
default: default,
|
90
|
+
required: required,
|
91
|
+
min: min,
|
92
|
+
max: max,
|
93
|
+
allow_nil: allow_nil
|
94
|
+
}
|
95
|
+
end
|
96
|
+
|
97
|
+
# asdasda
|
98
|
+
|
99
|
+
def positive_bignum_field(required: true, default: nil, min: 0, max: 2_000_000_000_000, allow_nil: false)
|
100
|
+
raise "This field's type must be numeric." if [min, max].any? { |value| !value.is_a?(Numeric) }
|
101
|
+
raise "This field's type must be boolean." if [required, allow_nil].any? { |value| !value.in? [true, false] }
|
102
|
+
raise 'Invalid numeric value.' unless (min >= 0) && (max <= 2_000_000_000_000)
|
103
|
+
|
104
|
+
{
|
105
|
+
type: 'num',
|
106
|
+
default: default,
|
107
|
+
required: required,
|
108
|
+
min: min,
|
109
|
+
max: max,
|
110
|
+
allow_nil: allow_nil
|
111
|
+
}
|
112
|
+
end
|
113
|
+
|
114
|
+
def positive_num_field(required: true, default: nil, min: 0, max: 2_000_000_000, allow_nil: false)
|
115
|
+
raise "This field's type must be numeric." if [min, max].any? { |value| !value.is_a?(Numeric) }
|
116
|
+
raise "This field's type must be boolean." if [required, allow_nil].any? { |value| !value.in? [true, false] }
|
117
|
+
raise 'Invalid numeric value.' unless (min >= 0) && (max <= 2_000_000_000)
|
118
|
+
|
119
|
+
{
|
120
|
+
type: 'num',
|
121
|
+
default: default,
|
122
|
+
required: required,
|
123
|
+
min: min,
|
124
|
+
max: max,
|
125
|
+
allow_nil: allow_nil
|
126
|
+
}
|
127
|
+
end
|
128
|
+
|
129
|
+
def positive_bigint_field(required: true, default: nil, min: 0, max: 2_000_000_000_000, allow_nil: false)
|
130
|
+
raise "This field's type must be integer." if [min, max].any? { |value| !value.is_a?(Integer) }
|
131
|
+
raise "This field's type must be boolean." if [required, allow_nil].any? { |value| !value.in? [true, false] }
|
132
|
+
raise 'Invalid integer value.' unless (min >= 0) && (max <= 2_000_000_000_000)
|
133
|
+
|
134
|
+
{
|
135
|
+
type: 'int',
|
136
|
+
default: default,
|
137
|
+
required: required,
|
138
|
+
min: min,
|
139
|
+
max: max,
|
140
|
+
allow_nil: allow_nil
|
141
|
+
}
|
142
|
+
end
|
143
|
+
|
144
|
+
def positive_int_field(required: true, default: nil, min: 0, max: 2_000_000_000, allow_nil: false)
|
145
|
+
raise "This field's type must be integer." if [min, max].any? { |value| !value.is_a?(Integer) }
|
146
|
+
raise "This field's type must be boolean." if [required, allow_nil].any? { |value| !value.in? [true, false] }
|
147
|
+
raise 'Invalid integer value.' unless (min >= 0) && (max <= 2_000_000_000)
|
148
|
+
|
149
|
+
{
|
150
|
+
type: 'int',
|
151
|
+
default: default,
|
152
|
+
required: required,
|
153
|
+
min: min,
|
154
|
+
max: max,
|
155
|
+
allow_nil: allow_nil
|
156
|
+
}
|
157
|
+
end
|
158
|
+
|
159
|
+
def arr_field(required: true, default: nil, allow_empty: false, allow_nil: false)
|
160
|
+
raise "This field's type must be boolean." if [required, allow_empty, allow_nil].any? { |value| !value.in? [true, false] }
|
161
|
+
|
162
|
+
{
|
163
|
+
type: 'arr',
|
164
|
+
default: default,
|
165
|
+
required: required,
|
166
|
+
allow_empty: allow_empty,
|
167
|
+
allow_nil: allow_nil
|
168
|
+
}
|
169
|
+
end
|
170
|
+
|
171
|
+
def date_field(required: true, default: nil, allow_nil: false)
|
172
|
+
raise "This field's type must be boolean." if [required, allow_nil].any? { |value| !value.in? [true, false] }
|
173
|
+
|
174
|
+
{
|
175
|
+
type: 'date',
|
176
|
+
default: default,
|
177
|
+
required: required,
|
178
|
+
allow_nil: allow_nil
|
179
|
+
}
|
180
|
+
end
|
181
|
+
|
182
|
+
def time_field(required: true, default: nil, allow_nil: false)
|
183
|
+
raise "This field's type must be boolean." if [required, allow_nil].any? { |value| !value.in? [true, false] }
|
184
|
+
|
185
|
+
{
|
186
|
+
type: 'time',
|
187
|
+
default: default,
|
188
|
+
required: required,
|
189
|
+
allow_nil: allow_nil
|
190
|
+
}
|
191
|
+
end
|
192
|
+
|
193
|
+
def datetime_field(required: true, default: nil, allow_nil: false)
|
194
|
+
raise "This field's type must be boolean." if [required, allow_nil].any? { |value| !value.in? [true, false] }
|
195
|
+
|
196
|
+
{
|
197
|
+
type: 'datetime',
|
198
|
+
default: default,
|
199
|
+
required: required,
|
200
|
+
allow_nil: allow_nil
|
201
|
+
}
|
202
|
+
end
|
203
|
+
|
204
|
+
def email_field(required: true, default: nil, allow_nil: false)
|
205
|
+
raise "This field's type must be boolean." if [required, allow_nil].any? { |value| !value.in? [true, false] }
|
206
|
+
|
207
|
+
{
|
208
|
+
type: 'email',
|
209
|
+
default: default,
|
210
|
+
required: required,
|
211
|
+
allow_nil: allow_nil
|
212
|
+
}
|
213
|
+
end
|
214
|
+
|
215
|
+
def boolean_field(required: true, default: nil, allow_nil: false)
|
216
|
+
raise "This field's type must be boolean." if [required, allow_nil].any? { |value| !value.in? [true, false] }
|
217
|
+
|
218
|
+
{
|
219
|
+
type: 'boolean',
|
220
|
+
default: default,
|
221
|
+
required: required,
|
222
|
+
allow_nil: allow_nil
|
223
|
+
}
|
224
|
+
end
|
225
|
+
|
226
|
+
end
|
227
|
+
|
228
|
+
end
|
@@ -0,0 +1,291 @@
|
|
1
|
+
module ParamsChecker
|
2
|
+
module ParamChecker
|
3
|
+
class BaseParamChecker
|
4
|
+
def initialize(key = '', fields = {}, opts = {})
|
5
|
+
@key = key
|
6
|
+
@fields = fields
|
7
|
+
@opts = opts
|
8
|
+
end
|
9
|
+
|
10
|
+
def call; end
|
11
|
+
|
12
|
+
def add_error(message = '')
|
13
|
+
errors.add(key, message)
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_accessor :key, :fields, :opts
|
17
|
+
end
|
18
|
+
|
19
|
+
class NumParamChecker < BaseParamChecker
|
20
|
+
prepend SimpleCommand
|
21
|
+
|
22
|
+
def call
|
23
|
+
return nil if fields[key][:allow_nil] && opts[key].nil?
|
24
|
+
|
25
|
+
check_type && check_param
|
26
|
+
opts[key]
|
27
|
+
end
|
28
|
+
|
29
|
+
def check_type
|
30
|
+
valid = opts[key].is_a? Numeric
|
31
|
+
add_error("This field's type must be numeric.") unless valid
|
32
|
+
valid
|
33
|
+
end
|
34
|
+
|
35
|
+
def check_param
|
36
|
+
min = fields[key][:min]
|
37
|
+
max = fields[key][:max]
|
38
|
+
valid =(min..max).include? opts[key]
|
39
|
+
add_error("This numeric field's value must be in range from #{min} to #{max}.") unless valid
|
40
|
+
valid
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class IntParamChecker < BaseParamChecker
|
45
|
+
prepend SimpleCommand
|
46
|
+
|
47
|
+
def call
|
48
|
+
return nil if fields[key][:allow_nil] && opts[key].nil?
|
49
|
+
|
50
|
+
check_type && check_param
|
51
|
+
opts[key]
|
52
|
+
end
|
53
|
+
|
54
|
+
def check_type
|
55
|
+
valid = opts[key].is_a? Integer
|
56
|
+
add_error("This field's type must be integer.") unless valid
|
57
|
+
valid
|
58
|
+
end
|
59
|
+
|
60
|
+
def check_param
|
61
|
+
min = fields[key][:min]
|
62
|
+
max = fields[key][:max]
|
63
|
+
valid = (min..max).include? opts[key]
|
64
|
+
add_error("This integer field's value must be in range from #{min} to #{max}.") unless valid
|
65
|
+
valid
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class CharParamChecker < BaseParamChecker
|
70
|
+
prepend SimpleCommand
|
71
|
+
|
72
|
+
def call
|
73
|
+
return nil if fields[key][:allow_nil] && opts[key].nil?
|
74
|
+
|
75
|
+
check_type && check_allow_blank && check_length && opts[key]
|
76
|
+
end
|
77
|
+
|
78
|
+
def check_type
|
79
|
+
valid = opts[key].is_a?(String)
|
80
|
+
add_error("This field's type must be string.") unless valid
|
81
|
+
valid
|
82
|
+
end
|
83
|
+
|
84
|
+
def check_allow_blank
|
85
|
+
valid = !(!fields[key][:allow_blank] && opts[key].blank?)
|
86
|
+
add_error('This field cannot be blank.') unless valid
|
87
|
+
valid
|
88
|
+
end
|
89
|
+
|
90
|
+
def check_length
|
91
|
+
min_length = fields[key][:min_length]
|
92
|
+
max_length = fields[key][:max_length]
|
93
|
+
valid = (min_length..max_length).include? opts[key].length
|
94
|
+
add_error("This string field's length must be in range from #{min_length} to #{max_length}.") unless valid
|
95
|
+
valid
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
class ArrParamChecker < BaseParamChecker
|
100
|
+
prepend SimpleCommand
|
101
|
+
|
102
|
+
def call
|
103
|
+
return nil if fields[key][:allow_nil] && opts[key].nil?
|
104
|
+
|
105
|
+
check_type && check_allow_empty && opts[key]
|
106
|
+
end
|
107
|
+
|
108
|
+
def check_type
|
109
|
+
valid =opts[key].is_a? Array
|
110
|
+
add_error("This field's type must be array.") unless valid
|
111
|
+
valid
|
112
|
+
end
|
113
|
+
|
114
|
+
def check_allow_empty
|
115
|
+
valid =!(!fields[key][:allow_empty] && opts[key].empty?)
|
116
|
+
add_error('This field cannot be empty.') unless valid
|
117
|
+
valid
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
class NestedHashChecker
|
122
|
+
prepend SimpleCommand
|
123
|
+
def initialize(key = '', fields = {}, opts = {}, context = {})
|
124
|
+
@key = key
|
125
|
+
@fields = fields
|
126
|
+
@opts = opts
|
127
|
+
@context = context
|
128
|
+
end
|
129
|
+
|
130
|
+
def call
|
131
|
+
return nil if fields[key][:allow_nil] && opts[key].nil?
|
132
|
+
|
133
|
+
check_type && formatted_nested_hash
|
134
|
+
end
|
135
|
+
|
136
|
+
def formatted_nested_hash
|
137
|
+
cmd = fields[key][:class].call(params:opts[key], context: context, is_outest_hash: false)
|
138
|
+
if cmd.success?
|
139
|
+
cmd.result
|
140
|
+
else
|
141
|
+
add_error cmd.errors
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def check_type
|
146
|
+
valid = opts[key].is_a?(ActionController::Parameters) || opts[key].is_a?(Hash)
|
147
|
+
add_error("This field's type must be object or ActionController::Parameters.") unless valid
|
148
|
+
valid
|
149
|
+
end
|
150
|
+
|
151
|
+
def add_error(message = '')
|
152
|
+
errors.add(key, message)
|
153
|
+
end
|
154
|
+
|
155
|
+
attr_accessor :key, :fields, :opts, :class, :context
|
156
|
+
end
|
157
|
+
|
158
|
+
class NestedHashsChecker
|
159
|
+
prepend SimpleCommand
|
160
|
+
def initialize(key = '', fields = {}, opts = {}, context = {})
|
161
|
+
@key = key
|
162
|
+
@fields = fields
|
163
|
+
@opts = opts
|
164
|
+
@context = context
|
165
|
+
end
|
166
|
+
|
167
|
+
def call
|
168
|
+
return nil if fields[key][:allow_nil] && opts[key].nil?
|
169
|
+
|
170
|
+
check_type && formatted_nested_hashs
|
171
|
+
end
|
172
|
+
|
173
|
+
def formatted_nested_hashs
|
174
|
+
opts[key].map do |nested_hash|
|
175
|
+
formatted_nested_hash(nested_hash)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def formatted_nested_hash nested_hash
|
180
|
+
cmd = fields[key][:class].call(params: nested_hash, context: context, is_outest_hash: false)
|
181
|
+
if cmd.success?
|
182
|
+
cmd.result
|
183
|
+
else
|
184
|
+
add_error cmd.errors
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def check_type
|
189
|
+
valid = opts[key].is_a?(Array)
|
190
|
+
add_error("This field's type must be array.") unless valid
|
191
|
+
valid
|
192
|
+
end
|
193
|
+
|
194
|
+
def add_error(message = '')
|
195
|
+
errors.add(key, message)
|
196
|
+
end
|
197
|
+
|
198
|
+
attr_accessor :key, :fields, :opts, :class, :context
|
199
|
+
end
|
200
|
+
|
201
|
+
class DateParamChecker < BaseParamChecker
|
202
|
+
prepend SimpleCommand
|
203
|
+
|
204
|
+
def call
|
205
|
+
return nil if fields[key][:allow_nil] && opts[key].nil?
|
206
|
+
|
207
|
+
formatted_date
|
208
|
+
end
|
209
|
+
|
210
|
+
def formatted_date
|
211
|
+
Date.parse opts[key]
|
212
|
+
rescue => e
|
213
|
+
add_error 'Invalid date.'
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
class TimeParamChecker < BaseParamChecker
|
218
|
+
prepend SimpleCommand
|
219
|
+
|
220
|
+
def call
|
221
|
+
return nil if fields[key][:allow_nil] && opts[key].nil?
|
222
|
+
|
223
|
+
formatted_time
|
224
|
+
end
|
225
|
+
|
226
|
+
def formatted_time
|
227
|
+
Time.parse opts[key]
|
228
|
+
rescue => e
|
229
|
+
add_error 'Invalid time.'
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
class DateTimeParamChecker < BaseParamChecker
|
234
|
+
prepend SimpleCommand
|
235
|
+
|
236
|
+
def call
|
237
|
+
return nil if fields[key][:allow_nil] && opts[key].nil?
|
238
|
+
|
239
|
+
formatted_datetime
|
240
|
+
end
|
241
|
+
|
242
|
+
def formatted_datetime
|
243
|
+
DateTime.parse(opts[key])
|
244
|
+
rescue => e
|
245
|
+
add_error 'Invalid datetime.'
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
class EmailParamChecker < BaseParamChecker
|
250
|
+
prepend SimpleCommand
|
251
|
+
|
252
|
+
def call
|
253
|
+
return nil if fields[key][:allow_nil] && opts[key].nil?
|
254
|
+
|
255
|
+
check_type && check_regrex && opts[key]
|
256
|
+
end
|
257
|
+
|
258
|
+
def check_type
|
259
|
+
valid = opts[key].is_a? String
|
260
|
+
add_error("Invalid email.") unless valid
|
261
|
+
valid
|
262
|
+
end
|
263
|
+
|
264
|
+
def check_regrex
|
265
|
+
valid = opts[key].match(URI::MailTo::EMAIL_REGEXP)
|
266
|
+
add_error('Invalid email.') unless valid
|
267
|
+
valid
|
268
|
+
end
|
269
|
+
|
270
|
+
end
|
271
|
+
|
272
|
+
class BooleanChecker < BaseParamChecker
|
273
|
+
prepend SimpleCommand
|
274
|
+
|
275
|
+
def call
|
276
|
+
return nil if fields[key][:allow_nil] && opts[key].nil?
|
277
|
+
|
278
|
+
check_type && opts[key]
|
279
|
+
end
|
280
|
+
|
281
|
+
def check_type
|
282
|
+
valid = opts[key].in? [true, false]
|
283
|
+
add_error("This field's type must be boolean.") unless valid
|
284
|
+
valid
|
285
|
+
end
|
286
|
+
|
287
|
+
end
|
288
|
+
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: params_checker
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- rexy tech
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-07-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 6.0.3
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 6.0.3.1
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 6.0.3
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 6.0.3.1
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: sqlite3
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
type: :development
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
description: Description of RexyAdmin.
|
48
|
+
email:
|
49
|
+
- ted@rexy.tech
|
50
|
+
executables: []
|
51
|
+
extensions: []
|
52
|
+
extra_rdoc_files: []
|
53
|
+
files:
|
54
|
+
- MIT-LICENSE
|
55
|
+
- README.md
|
56
|
+
- Rakefile
|
57
|
+
- app/assets/config/params_checker_manifest.js
|
58
|
+
- app/assets/stylesheets/params_checker/application.css
|
59
|
+
- app/controllers/params_checker/application_controller.rb
|
60
|
+
- app/helpers/params_checker/application_helper.rb
|
61
|
+
- app/jobs/params_checker/application_job.rb
|
62
|
+
- app/mailers/params_checker/application_mailer.rb
|
63
|
+
- app/models/params_checker/application_record.rb
|
64
|
+
- app/views/layouts/params_checker/application.html.erb
|
65
|
+
- config/routes.rb
|
66
|
+
- lib/params_checker.rb
|
67
|
+
- lib/params_checker/base_params_checker.rb
|
68
|
+
- lib/params_checker/engine.rb
|
69
|
+
- lib/params_checker/fields.rb
|
70
|
+
- lib/params_checker/my_error.rb
|
71
|
+
- lib/params_checker/param_checker.rb
|
72
|
+
- lib/params_checker/version.rb
|
73
|
+
homepage: https://rexy.tech/
|
74
|
+
licenses:
|
75
|
+
- MIT
|
76
|
+
metadata: {}
|
77
|
+
post_install_message:
|
78
|
+
rdoc_options: []
|
79
|
+
require_paths:
|
80
|
+
- lib
|
81
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
requirements: []
|
92
|
+
rubygems_version: 3.1.4
|
93
|
+
signing_key:
|
94
|
+
specification_version: 4
|
95
|
+
summary: ParamsChecker.
|
96
|
+
test_files: []
|