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 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
+ */
@@ -0,0 +1,5 @@
1
+ module ParamsChecker
2
+ class ApplicationController < ActionController::Base
3
+ protect_from_forgery with: :exception
4
+ end
5
+ end
@@ -0,0 +1,4 @@
1
+ module ParamsChecker
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module ParamsChecker
2
+ class ApplicationJob < ActiveJob::Base
3
+ end
4
+ end
@@ -0,0 +1,6 @@
1
+ module ParamsChecker
2
+ class ApplicationMailer < ActionMailer::Base
3
+ default from: 'from@example.com'
4
+ layout 'mailer'
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module ParamsChecker
2
+ class ApplicationRecord < ActiveRecord::Base
3
+ self.abstract_class = true
4
+ end
5
+ end
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Params checker</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
+
8
+ <%= stylesheet_link_tag "params_checker/application", media: "all" %>
9
+ </head>
10
+ <body>
11
+
12
+ <%= yield %>
13
+
14
+ </body>
15
+ </html>
data/config/routes.rb ADDED
@@ -0,0 +1,2 @@
1
+ ParamsChecker::Engine.routes.draw do
2
+ end
@@ -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,7 @@
1
+ module ParamsChecker
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace ParamsChecker
4
+ end
5
+ class NotEngine
6
+ end
7
+ end
@@ -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,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ParamsChecker
4
+ class MyError < StandardError
5
+ def initialize(message)
6
+ super(message)
7
+ end
8
+ end
9
+ 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
+
@@ -0,0 +1,3 @@
1
+ module ParamsChecker
2
+ VERSION = '0.2.1'
3
+ end
@@ -0,0 +1,9 @@
1
+ require "simple_command"
2
+ require "params_checker/engine"
3
+ require "params_checker/fields"
4
+ require "params_checker/my_error"
5
+ require "params_checker/param_checker"
6
+ require "params_checker/base_params_checker"
7
+ module ParamsChecker
8
+ end
9
+
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: []