vanilla_validator 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +96 -0
- data/README.md +158 -0
- data/Rakefile +4 -0
- data/lib/locale/en.yml +87 -0
- data/lib/vanilla_validator/helpers.rb +87 -0
- data/lib/vanilla_validator/railtie.rb +39 -0
- data/lib/vanilla_validator/result.rb +15 -0
- data/lib/vanilla_validator/rule.rb +10 -0
- data/lib/vanilla_validator/rule_parser.rb +44 -0
- data/lib/vanilla_validator/rules/after.rb +13 -0
- data/lib/vanilla_validator/rules/after_or_equal.rb +13 -0
- data/lib/vanilla_validator/rules/base_rule.rb +17 -0
- data/lib/vanilla_validator/rules/before.rb +13 -0
- data/lib/vanilla_validator/rules/before_or_equal.rb +13 -0
- data/lib/vanilla_validator/rules/block_rule.rb +19 -0
- data/lib/vanilla_validator/rules/boolean.rb +13 -0
- data/lib/vanilla_validator/rules/date.rb +19 -0
- data/lib/vanilla_validator/rules/email.rb +13 -0
- data/lib/vanilla_validator/rules/eq.rb +13 -0
- data/lib/vanilla_validator/rules/falsy.rb +14 -0
- data/lib/vanilla_validator/rules/gte.rb +13 -0
- data/lib/vanilla_validator/rules/in.rb +13 -0
- data/lib/vanilla_validator/rules/like.rb +14 -0
- data/lib/vanilla_validator/rules/max.rb +13 -0
- data/lib/vanilla_validator/rules/min.rb +13 -0
- data/lib/vanilla_validator/rules/numeric.rb +14 -0
- data/lib/vanilla_validator/rules/other_rule.rb +40 -0
- data/lib/vanilla_validator/rules/required.rb +21 -0
- data/lib/vanilla_validator/rules/required_if.rb +15 -0
- data/lib/vanilla_validator/rules/url.rb +13 -0
- data/lib/vanilla_validator/value_extractor.rb +93 -0
- data/lib/vanilla_validator/version.rb +5 -0
- data/lib/vanilla_validator.rb +103 -0
- metadata +137 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: eb035f079a5c22180c9824294d979c0aeefd71fc71ff87233bf4520d64d81f14
|
4
|
+
data.tar.gz: 21e7fe1cd16419549f74a7ff9b9828adea78ff134fed11e6f5e95fefc9097653
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4b796d246078765d99c74abd6b5891f9cd20c827717ea317f984a15737c2498365538850e72f10d56844ebc34466cb8f16b0d0a518d25b303ad5226fcdb03d85
|
7
|
+
data.tar.gz: 8a89d30b83e550f88b6b4eba8cfdcb91f91d32bfee03c5c7a12a719e1920e739c1db82d113ca8ea212c6a7a204f7a5cf42b022411dbbbe5ce2be615e188b914d
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
vanilla_validator (0.1.4)
|
5
|
+
activesupport
|
6
|
+
i18n
|
7
|
+
zeitwerk (~> 2.5)
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: https://rubygems.org/
|
11
|
+
specs:
|
12
|
+
actionpack (7.1.1)
|
13
|
+
actionview (= 7.1.1)
|
14
|
+
activesupport (= 7.1.1)
|
15
|
+
nokogiri (>= 1.8.5)
|
16
|
+
rack (>= 2.2.4)
|
17
|
+
rack-session (>= 1.0.1)
|
18
|
+
rack-test (>= 0.6.3)
|
19
|
+
rails-dom-testing (~> 2.2)
|
20
|
+
rails-html-sanitizer (~> 1.6)
|
21
|
+
actionview (7.1.1)
|
22
|
+
activesupport (= 7.1.1)
|
23
|
+
builder (~> 3.1)
|
24
|
+
erubi (~> 1.11)
|
25
|
+
rails-dom-testing (~> 2.2)
|
26
|
+
rails-html-sanitizer (~> 1.6)
|
27
|
+
activesupport (7.1.1)
|
28
|
+
base64
|
29
|
+
bigdecimal
|
30
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
31
|
+
connection_pool (>= 2.2.5)
|
32
|
+
drb
|
33
|
+
i18n (>= 1.6, < 2)
|
34
|
+
minitest (>= 5.1)
|
35
|
+
mutex_m
|
36
|
+
tzinfo (~> 2.0)
|
37
|
+
base64 (0.1.1)
|
38
|
+
bigdecimal (3.1.4)
|
39
|
+
builder (3.2.4)
|
40
|
+
concurrent-ruby (1.1.10)
|
41
|
+
connection_pool (2.4.1)
|
42
|
+
crass (1.0.6)
|
43
|
+
diff-lcs (1.5.0)
|
44
|
+
drb (2.1.1)
|
45
|
+
ruby2_keywords
|
46
|
+
erubi (1.12.0)
|
47
|
+
i18n (1.12.0)
|
48
|
+
concurrent-ruby (~> 1.0)
|
49
|
+
loofah (2.21.4)
|
50
|
+
crass (~> 1.0.2)
|
51
|
+
nokogiri (>= 1.12.0)
|
52
|
+
minitest (5.20.0)
|
53
|
+
mutex_m (0.1.2)
|
54
|
+
nokogiri (1.15.4-x86_64-linux)
|
55
|
+
racc (~> 1.4)
|
56
|
+
racc (1.7.3)
|
57
|
+
rack (3.0.8)
|
58
|
+
rack-session (2.0.0)
|
59
|
+
rack (>= 3.0.0)
|
60
|
+
rack-test (2.1.0)
|
61
|
+
rack (>= 1.3)
|
62
|
+
rails-dom-testing (2.2.0)
|
63
|
+
activesupport (>= 5.0.0)
|
64
|
+
minitest
|
65
|
+
nokogiri (>= 1.6)
|
66
|
+
rails-html-sanitizer (1.6.0)
|
67
|
+
loofah (~> 2.21)
|
68
|
+
nokogiri (~> 1.14)
|
69
|
+
rspec (3.11.0)
|
70
|
+
rspec-core (~> 3.11.0)
|
71
|
+
rspec-expectations (~> 3.11.0)
|
72
|
+
rspec-mocks (~> 3.11.0)
|
73
|
+
rspec-core (3.11.0)
|
74
|
+
rspec-support (~> 3.11.0)
|
75
|
+
rspec-expectations (3.11.0)
|
76
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
77
|
+
rspec-support (~> 3.11.0)
|
78
|
+
rspec-mocks (3.11.1)
|
79
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
80
|
+
rspec-support (~> 3.11.0)
|
81
|
+
rspec-support (3.11.0)
|
82
|
+
ruby2_keywords (0.0.5)
|
83
|
+
tzinfo (2.0.6)
|
84
|
+
concurrent-ruby (~> 1.0)
|
85
|
+
zeitwerk (2.6.12)
|
86
|
+
|
87
|
+
PLATFORMS
|
88
|
+
x86_64-linux
|
89
|
+
|
90
|
+
DEPENDENCIES
|
91
|
+
actionpack
|
92
|
+
rspec (~> 3.2)
|
93
|
+
vanilla_validator!
|
94
|
+
|
95
|
+
BUNDLED WITH
|
96
|
+
2.3.19
|
data/README.md
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
## 🚧 Project Under Development 🚧
|
2
|
+
|
3
|
+
## VanillaValidator
|
4
|
+
|
5
|
+
VanillaValidator is a lightweight and clean solution for implementing validation in Ruby. It inspired from Laravel Validator and allows you to separate validations from the model layer in your Rails applications. With this gem, you can easily define and enforce validation rules for input data, ensuring the consistency and cleanliness of your application's data.
|
6
|
+
|
7
|
+
### Installation:
|
8
|
+
To use VanillaValidator in your Ruby project, execute the following command to install it:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
$ bundle add vanilla_validator
|
12
|
+
```
|
13
|
+
|
14
|
+
### Basic Usage
|
15
|
+
There are two options to use VanillaValidator, in the first place you can invoke `validate` method directlly from `VanillaValidator` class and then result would be an object witch contains different methods to determine the result of validation.
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
params = {
|
19
|
+
user: {
|
20
|
+
email: 'john@doe.me'
|
21
|
+
}
|
22
|
+
}
|
23
|
+
|
24
|
+
validation = VanillaValidator.validate(params, {
|
25
|
+
'user.email' => 'required|email'
|
26
|
+
})
|
27
|
+
|
28
|
+
validation.success?
|
29
|
+
validation.failed?
|
30
|
+
validation.validated
|
31
|
+
validation.errors
|
32
|
+
|
33
|
+
|
34
|
+
# In Rails, you can access the validate method directly:
|
35
|
+
params.validate({
|
36
|
+
'user.email' => 'require|email'
|
37
|
+
})
|
38
|
+
|
39
|
+
# If you want validation to stop at the first failure, use a bang sign (!) after 'validate':
|
40
|
+
params.validate!({
|
41
|
+
'user.password' => 'require|min:16'
|
42
|
+
})
|
43
|
+
```
|
44
|
+
|
45
|
+
### Rules Declaration
|
46
|
+
You have the flexibility to define validation rules either explicitly or implicitly, depending on your specific requirements. When taking the explicit approach, you must specify the exact attribute you wish to validate. To access nested attributes, you can employ a period (.) in the attribute path, as demonstrated below:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
params = {
|
50
|
+
user: {
|
51
|
+
email: 'john@doe.me',
|
52
|
+
preferences: {
|
53
|
+
notifications: true
|
54
|
+
}
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
VanillaValidator.validate(params, {
|
59
|
+
'user.email' => 'required|email',
|
60
|
+
'user.preferences.notifications' => 'boolean'
|
61
|
+
})
|
62
|
+
```
|
63
|
+
|
64
|
+
In cases where your input consists of a collection of items, you can specify the attributes implicitly. This can be achieved by using a wildcard (\*) in the attribute path, as shown in the following example:
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
params = {
|
68
|
+
user: {
|
69
|
+
addresses: [
|
70
|
+
{ city: 'San Francisco', state: 'CA' },
|
71
|
+
{ city: 'Los Angeles', state: 'CA' }
|
72
|
+
],
|
73
|
+
orders: [
|
74
|
+
{ total: 50.0, status: 'shipped' },
|
75
|
+
{ total: 75.0, status: 'delivered' }
|
76
|
+
]
|
77
|
+
}
|
78
|
+
}
|
79
|
+
|
80
|
+
validation = VanillaValidator.validate(params, {
|
81
|
+
'user.addresses.*.state' => 'required|string|in:CA,NY',
|
82
|
+
'user.orders.*.total' => 'required|numeric|min:0',
|
83
|
+
'user.orders.*.status' => 'required|string|in:pending,shipped,delivered'
|
84
|
+
})
|
85
|
+
```
|
86
|
+
|
87
|
+
### Available Validation Rules
|
88
|
+
- [After](#after)
|
89
|
+
- [AfterOrEqual](#after_or_equal)
|
90
|
+
- [Before](#before)
|
91
|
+
- [BeforeOrEqual](#before_or_equal)
|
92
|
+
- [Boolean](#boolean)
|
93
|
+
- [Date](#date)
|
94
|
+
- [Email](#email)
|
95
|
+
- [EQ](#eq)
|
96
|
+
- [Falsy](#falsy)
|
97
|
+
- [Gte](#gte)
|
98
|
+
- [In](#in)
|
99
|
+
- [Like](#like)
|
100
|
+
- [Max](#max)
|
101
|
+
- [Min](#min)
|
102
|
+
- [Numeric](#numeric)
|
103
|
+
- [Required](#required)
|
104
|
+
- [RequiredIf](#required_if)
|
105
|
+
- [Url](#url)
|
106
|
+
- [Custom Validation Rules](#custom_validation_rules)
|
107
|
+
|
108
|
+
##### After
|
109
|
+
The validated field must have a value that is after a specified date.
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
'start_date' => 'required|date|after:tomorrow'
|
113
|
+
```
|
114
|
+
|
115
|
+
##### After Or Equal
|
116
|
+
|
117
|
+
##### Before
|
118
|
+
|
119
|
+
##### Before Or Equal
|
120
|
+
|
121
|
+
##### Boolean
|
122
|
+
|
123
|
+
##### Date
|
124
|
+
|
125
|
+
##### Email
|
126
|
+
|
127
|
+
##### EQ
|
128
|
+
|
129
|
+
##### Falsy
|
130
|
+
|
131
|
+
##### Gte
|
132
|
+
|
133
|
+
##### In
|
134
|
+
|
135
|
+
##### Like
|
136
|
+
|
137
|
+
##### Max
|
138
|
+
|
139
|
+
##### Min
|
140
|
+
|
141
|
+
##### Numeric
|
142
|
+
|
143
|
+
##### Required
|
144
|
+
|
145
|
+
##### Required If
|
146
|
+
|
147
|
+
##### Url
|
148
|
+
|
149
|
+
##### Custom Validation Rules:
|
150
|
+
|
151
|
+
### Contributions:
|
152
|
+
Contributions to this gem are welcome. Please read the [Contribution Guidelines](link-to-contributing) before submitting your contributions.
|
153
|
+
|
154
|
+
### Reporting Issues:
|
155
|
+
If you encounter any issues or have suggestions for improvements, please open an issue on the [GitHub repository](link-to-issues).
|
156
|
+
|
157
|
+
### License:
|
158
|
+
This gem is available under the [MIT License](https://choosealicense.com/licenses/mit/).
|
data/Rakefile
ADDED
data/lib/locale/en.yml
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
en:
|
2
|
+
url: 'The %{attribute} must be a valid URL.'
|
3
|
+
after: 'The %{attribute} must be a date after %{date}.'
|
4
|
+
after_or_equal: 'The %{attribute} must be a date after or equal to %{date}.'
|
5
|
+
before: 'The %{attribute} must be a date before %{date}.'
|
6
|
+
before_or_equal: 'The %{attribute} must be a date before or equal to %{date}.'
|
7
|
+
alpha: 'The %{attribute} must only contain letters.'
|
8
|
+
alpha_dash: 'The %{attribute} must only contain letters, numbers, dashes and underscores.'
|
9
|
+
alpha_num: 'The %{attribute} must only contain letters and numbers.'
|
10
|
+
array: 'The %{attribute} must be an array.'
|
11
|
+
between:
|
12
|
+
array: 'The %{attribute} must have between %{min} and %{max} items.'
|
13
|
+
file: 'The %{attribute} must be between %{min} and %{max} kilobytes.'
|
14
|
+
numeric: 'The %{attribute} must be between %{min} and %{max}.'
|
15
|
+
string: 'The %{attribute} must be between %{min} and %{max} characters.'
|
16
|
+
boolean: 'The %{attribute} field must be true or false.'
|
17
|
+
falsy: 'The %{attribute} is not a falsy value.'
|
18
|
+
eq: 'The %{attribute} should be equal to %{value}'
|
19
|
+
like: 'The %{attribute} should be like %{other_attribute}'
|
20
|
+
date: 'The %{attribute} is not a valid date.'
|
21
|
+
date_equals: 'The %{attribute} must be a date equal to %{date}.'
|
22
|
+
date_format: 'The %{attribute} does not match the format %{format}.'
|
23
|
+
different: 'The %{attribute} and %{other} must be different.'
|
24
|
+
digits: 'The %{attribute} must be %{digits} digits.'
|
25
|
+
digits_between: 'The %{attribute} must be between %{min} and %{max} digits.'
|
26
|
+
distinct: 'The %{attribute} field has a duplicate value.'
|
27
|
+
email: 'The %{attribute} must be a valid email address.'
|
28
|
+
enum: 'The selected %{attribute} is invalid.'
|
29
|
+
exists: 'The selected %{attribute} is invalid.'
|
30
|
+
file: 'The %{attribute} must be a file.'
|
31
|
+
filled: 'The %{attribute} field must have a value.'
|
32
|
+
gt:
|
33
|
+
array: 'The %{attribute} must have more than %{value} items.'
|
34
|
+
file: 'The %{attribute} must be greater than %{value} kilobytes.'
|
35
|
+
numeric: 'The %{attribute} must be greater than %{value}.'
|
36
|
+
string: 'The %{attribute} must be greater than %{value} characters.'
|
37
|
+
gte:
|
38
|
+
array: 'The %{attribute} must have %{value} items or more.'
|
39
|
+
file: 'The %{attribute} must be greater than or equal to %{value} kilobytes.'
|
40
|
+
numeric: 'The %{attribute} must be greater than or equal to %{value}.'
|
41
|
+
string: 'The %{attribute} must be greater than or equal to %{value} characters.'
|
42
|
+
image: 'The %{attribute} must be an image.'
|
43
|
+
in: 'The selected %{attribute} is invalid.'
|
44
|
+
integer: 'The %{attribute} must be an integer.'
|
45
|
+
ip: 'The %{attribute} must be a valid IP address.'
|
46
|
+
ipv4: 'The %{attribute} must be a valid IPv4 address.'
|
47
|
+
ipv6: 'The %{attribute} must be a valid IPv6 address.'
|
48
|
+
json: 'The %{attribute} must be a valid JSON string.'
|
49
|
+
lt:
|
50
|
+
array: 'The %{attribute} must have less than %{value} items.'
|
51
|
+
file: 'The %{attribute} must be less than %{value} kilobytes.'
|
52
|
+
numeric: 'The %{attribute} must be less than %{value}.'
|
53
|
+
string: 'The %{attribute} must be less than %{value} characters.'
|
54
|
+
lte:
|
55
|
+
array: 'The %{attribute} must not have more than %{value} items.'
|
56
|
+
file: 'The %{attribute} must be less than or equal to %{value} kilobytes.'
|
57
|
+
numeric: 'The %{attribute} must be less than or equal to %{value}.'
|
58
|
+
string: 'The %{attribute} must be less than or equal to %{value} characters.'
|
59
|
+
mac_address: 'The %{attribute} must be a valid MAC address.'
|
60
|
+
max:
|
61
|
+
array: 'The %{attribute} must not have more than %{max} items.'
|
62
|
+
file: 'The %{attribute} must not be greater than %{max} kilobytes.'
|
63
|
+
numeric: 'The %{attribute} must not be greater than %{max}.'
|
64
|
+
string: 'The %{attribute} must not be greater than %{max} characters.'
|
65
|
+
max_digits: 'The %{attribute} must not have more than %{max} digits.'
|
66
|
+
mimes: 'The %{attribute} must be a file of type: %{values}.'
|
67
|
+
mimetypes: 'The %{attribute} must be a file of type: %{values}.'
|
68
|
+
min:
|
69
|
+
array: 'The %{attribute} must have at least %{min} items.'
|
70
|
+
file: 'The %{attribute} must be at least %{min} kilobytes.'
|
71
|
+
numeric: 'The %{attribute} must be at least %{min}.'
|
72
|
+
string: 'The %{attribute} must be at least %{min} characters.'
|
73
|
+
min_digits: 'The %{attribute} must have at least %{min} digits.'
|
74
|
+
not_in: 'The selected %{attribute} is invalid.'
|
75
|
+
numeric: 'The %{attribute} must be a number.'
|
76
|
+
present: 'The %{attribute} field must be present.'
|
77
|
+
regex: 'The %{attribute} format is invalid.'
|
78
|
+
required: 'The %{attribute} field is required.'
|
79
|
+
required_if: 'The %{attribute} field is required when %{other} is %{value}.'
|
80
|
+
required_unless: 'The %{attribute} field is required unless %{other} is in %{value}s.'
|
81
|
+
unique: 'The %{attribute} has already been taken.'
|
82
|
+
custom:
|
83
|
+
attribute_name:
|
84
|
+
rule_name: 'Message'
|
85
|
+
foo:
|
86
|
+
proc: 'The %{attribute} does not statisfied'
|
87
|
+
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module VanillaValidator
|
2
|
+
# Helpers module contains various utility methods used by the VanillaValidator module.
|
3
|
+
module Helpers
|
4
|
+
private
|
5
|
+
|
6
|
+
# Private: Deep clone the input data while nullifying certain values.
|
7
|
+
#
|
8
|
+
# data - The input data to clone.
|
9
|
+
#
|
10
|
+
# Returns: A deep clone of the input data with specific values nullified.
|
11
|
+
#
|
12
|
+
def deep_clone_input(data)
|
13
|
+
new_input = Marshal.load(Marshal.dump(data))
|
14
|
+
nullify_values(new_input)
|
15
|
+
new_input
|
16
|
+
end
|
17
|
+
|
18
|
+
# Private: Recursively nullify values in a hash.
|
19
|
+
#
|
20
|
+
# hash - The hash in which values are to be nullified.
|
21
|
+
#
|
22
|
+
# Returns: The hash with specific values replaced by '__missing__'.
|
23
|
+
#
|
24
|
+
def nullify_values(hash)
|
25
|
+
hash.each do |key, value|
|
26
|
+
if value.is_a?(Hash)
|
27
|
+
nullify_values(value)
|
28
|
+
elsif value.is_a?(Array)
|
29
|
+
value.each { |item| nullify_values(item) if item.is_a?(Hash) }
|
30
|
+
else
|
31
|
+
hash[key] = '__missing__'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Private: Set data within a nested structure based on a provided key.
|
37
|
+
#
|
38
|
+
# array - The nested data structure to modify.
|
39
|
+
# key - The key specifying the location to set the value.
|
40
|
+
# value - The value to set.
|
41
|
+
#
|
42
|
+
# Returns: The modified nested data structure.
|
43
|
+
#
|
44
|
+
def data_set(array, key, value)
|
45
|
+
keys = key.split(".")
|
46
|
+
last_key = keys.pop
|
47
|
+
|
48
|
+
target = keys.reduce(array) do |hash, k|
|
49
|
+
case k
|
50
|
+
when "*"
|
51
|
+
hash.last ||= {}
|
52
|
+
hash.last
|
53
|
+
else
|
54
|
+
hash[k] ||= {}
|
55
|
+
hash[k]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
if last_key == "*"
|
60
|
+
target << value
|
61
|
+
else
|
62
|
+
target[last_key] = value
|
63
|
+
end
|
64
|
+
|
65
|
+
array
|
66
|
+
end
|
67
|
+
|
68
|
+
# Private: Remove entries with '__missing__' values from a hash.
|
69
|
+
#
|
70
|
+
# hash - The hash from which entries with '__missing__' values are to be removed.
|
71
|
+
#
|
72
|
+
# Returns: The hash with '__missing__' values removed.
|
73
|
+
#
|
74
|
+
def delete_missing_values(hash)
|
75
|
+
hash.each do |k, v|
|
76
|
+
if v == '__missing__'
|
77
|
+
hash.delete(k)
|
78
|
+
elsif v.kind_of?(Array)
|
79
|
+
hash[k] = v.reject { |item| item == '__missing__' }
|
80
|
+
elsif v.kind_of?(Hash)
|
81
|
+
hash[k] = delete_missing_values(v)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
return hash
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# The VanillaValidator::Railtie class is responsible for integrating validation
|
4
|
+
# methods into ActionController::Parameters in a Ruby on Rails application.
|
5
|
+
|
6
|
+
require 'rails/railtie'
|
7
|
+
|
8
|
+
module VanillaValidator
|
9
|
+
class Railtie < ::Rails::Railtie
|
10
|
+
# Initializes and configures the integration of validation methods.
|
11
|
+
initializer 'vanilla_validator' do
|
12
|
+
ActiveSupport.on_load :action_controller do
|
13
|
+
# Include the ValidationExtensions module within ActionController::Parameters.
|
14
|
+
ActionController::Parameters.include(ValidationExtensions)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# The ValidationExtensions module provides methods for validating
|
20
|
+
# ActionController::Parameters against a specified contract.
|
21
|
+
module ValidationExtensions
|
22
|
+
# Validates the ActionController::Parameters against the specified contract.
|
23
|
+
#
|
24
|
+
# @param contract [Hash] A contract specifying validation rules.
|
25
|
+
#
|
26
|
+
# @return [Object] The result of the validation.
|
27
|
+
def validate(contract)
|
28
|
+
VanillaValidator.validate(self.to_unsafe_h, contract)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Validates the ActionController::Parameters against the specified contract
|
32
|
+
# and raises an exception if the validation fails.
|
33
|
+
#
|
34
|
+
# @param contract [Hash] A contract specifying validation rules.
|
35
|
+
def validate!(contract)
|
36
|
+
VanillaValidator.validate!(self.to_unsafe_h, contract)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module VanillaValidator
|
2
|
+
# Result represents the outcome of a validation operation, including validated data and errors.
|
3
|
+
class Result
|
4
|
+
attr_accessor :validated, :errors
|
5
|
+
|
6
|
+
def initialize(validated, errors = {})
|
7
|
+
@validated = validated
|
8
|
+
@errors = errors
|
9
|
+
end
|
10
|
+
|
11
|
+
def valid?
|
12
|
+
errors.empty?
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module VanillaValidator
|
4
|
+
# RuleParser is responsible for parsing validation rules defined in a contract term.
|
5
|
+
class RuleParser
|
6
|
+
# Public: Parse a contract term to extract validation rules.
|
7
|
+
#
|
8
|
+
# term - The contract term to parse, which may include one or more validation rules separated by '|'.
|
9
|
+
#
|
10
|
+
# Returns: An array of Rule objects representing the parsed validation rules.
|
11
|
+
#
|
12
|
+
# Examples:
|
13
|
+
# RuleParser.parse('required|min:5') #=> [Rule.new('required', []), Rule.new('min_length', ['5'])]
|
14
|
+
#
|
15
|
+
def self.parse(term)
|
16
|
+
if term.respond_to?(:call)
|
17
|
+
[Rule.new('block_rule', term)]
|
18
|
+
elsif term.respond_to?(:valid?)
|
19
|
+
[Rule.new('custom_rule', term)]
|
20
|
+
else
|
21
|
+
parse_rules(term)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
# Private: Parse individual validation rules from a contract term.
|
28
|
+
#
|
29
|
+
# term - The contract term to parse, which may include one or more validation rules separated by '|'.
|
30
|
+
#
|
31
|
+
# Returns: An array of Rule objects representing the parsed validation rules.
|
32
|
+
#
|
33
|
+
def self.parse_rules(term)
|
34
|
+
rules = term.split('|')
|
35
|
+
|
36
|
+
rules.map do |rule|
|
37
|
+
rule_name, params = rule.split(':') if rule.respond_to?(:split)
|
38
|
+
parameters = params.split(',') if params.respond_to?(:split)
|
39
|
+
|
40
|
+
Rule.new(rule_name, parameters)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module VanillaValidator
|
2
|
+
module Rules
|
3
|
+
class After < BaseRule
|
4
|
+
def valid?
|
5
|
+
::Date.parse(value, '%Y-%m-%d') > ::Date.parse(parameters[0], '%Y-%m-%d')
|
6
|
+
end
|
7
|
+
|
8
|
+
def failure_message
|
9
|
+
I18n.t('after', attribute: attribute, date: parameters[0])
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module VanillaValidator
|
2
|
+
module Rules
|
3
|
+
class AfterOrEqual < BaseRule
|
4
|
+
def valid?
|
5
|
+
::Date.parse(value, '%Y-%m-%d') >= ::Date.parse(parameters[0], '%Y-%m-%d')
|
6
|
+
end
|
7
|
+
|
8
|
+
def failure_message
|
9
|
+
I18n.t('after_or_equal', attribute: attribute, date: parameters[0])
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module VanillaValidator
|
2
|
+
module Rules
|
3
|
+
class BaseRule
|
4
|
+
attr_accessor :attribute, :value, :parameters
|
5
|
+
|
6
|
+
def initialize(attribute, value, parameters)
|
7
|
+
@attribute, @value, @parameters = attribute, value, parameters
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def required?
|
13
|
+
Rules::Required.new(attribute, value, parameters).valid?
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module VanillaValidator
|
2
|
+
module Rules
|
3
|
+
class Before < BaseRule
|
4
|
+
def valid?
|
5
|
+
::Date.parse(value, '%Y-%m-%d') < ::Date.parse(parameters[0], '%Y-%m-%d')
|
6
|
+
end
|
7
|
+
|
8
|
+
def failure_message
|
9
|
+
I18n.t('after', attribute: attribute, date: parameters[0])
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module VanillaValidator
|
2
|
+
module Rules
|
3
|
+
class BeforeOrEqual < BaseRule
|
4
|
+
def valid?
|
5
|
+
::Date.parse(value, '%Y-%m-%d') <= ::Date.parse(parameters[0], '%Y-%m-%d')
|
6
|
+
end
|
7
|
+
|
8
|
+
def failure_message
|
9
|
+
I18n.t('before_or_equal', attribute: attribute, date: parameters[0])
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module VanillaValidator
|
2
|
+
module Rules
|
3
|
+
class BlockRule < BaseRule
|
4
|
+
|
5
|
+
attr_accessor :message
|
6
|
+
|
7
|
+
def valid?
|
8
|
+
block = parameters
|
9
|
+
block.call(attribute, value, ->(msg){ self.message = msg })
|
10
|
+
|
11
|
+
message.nil? ? true : false
|
12
|
+
end
|
13
|
+
|
14
|
+
def failure_message
|
15
|
+
message
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module VanillaValidator
|
2
|
+
module Rules
|
3
|
+
class Date < BaseRule
|
4
|
+
def valid?
|
5
|
+
begin
|
6
|
+
::Date.strptime(value, '%Y-%m-%d')
|
7
|
+
true
|
8
|
+
rescue
|
9
|
+
# ArgumentError, TypeError
|
10
|
+
false
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def failure_message
|
15
|
+
I18n.t('date', attribute: attribute)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module VanillaValidator
|
2
|
+
module Rules
|
3
|
+
class Falsy < BaseRule
|
4
|
+
def valid?
|
5
|
+
acceptable = ['no', 'off', '0', 0, false, 'false']
|
6
|
+
required? && acceptable.include?(value)
|
7
|
+
end
|
8
|
+
|
9
|
+
def failure_message
|
10
|
+
I18n.t('falsy', attribute: attribute)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module VanillaValidator
|
2
|
+
module Rules
|
3
|
+
class Like < BaseRule
|
4
|
+
def valid?
|
5
|
+
other_value = ValueExtractor.get(VanillaValidator.raw_input, parameters[0])
|
6
|
+
value == other_value
|
7
|
+
end
|
8
|
+
|
9
|
+
def failure_message
|
10
|
+
I18n.t('like', attribute: attribute, other_attribute: parameters[0])
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module VanillaValidator
|
2
|
+
module Rules
|
3
|
+
class Numeric < BaseRule
|
4
|
+
def valid?
|
5
|
+
return true if value.kind_of?(Numeric)
|
6
|
+
!!(Integer(value) rescue Float(value)) rescue false
|
7
|
+
end
|
8
|
+
|
9
|
+
def failure_message
|
10
|
+
I18n.t("numeric", attribute: attribute)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module VanillaValidator
|
2
|
+
module Rules
|
3
|
+
class OtherRule
|
4
|
+
attr_accessor :name, :attribute, :value, :parameters, :klass
|
5
|
+
|
6
|
+
DEFAULT_RULE_NAME = 'eq'.freeze
|
7
|
+
|
8
|
+
def initialize(input, term_array)
|
9
|
+
self.attribute = term_array[0]
|
10
|
+
self.name = term_array.length == 2 ? DEFAULT_RULE_NAME : term_array[1]
|
11
|
+
self.parameters = self.normalize(term_array[name == DEFAULT_RULE_NAME ? 1..-1 : 2..-1])
|
12
|
+
self.value = ValueExtractor.get(input, attribute)
|
13
|
+
self.klass = self.initialize_rule(name, value, parameters)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.call(input, term_array)
|
17
|
+
self.new(input, term_array)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def normalize(parameters)
|
23
|
+
parameters.map do |parameter|
|
24
|
+
case parameter.downcase
|
25
|
+
when 'true' then true
|
26
|
+
when 'false' then false
|
27
|
+
when /\A\d+\z/ then parameter.to_i
|
28
|
+
when /\A\d+\.\d+\z/ then parameter.to_f
|
29
|
+
else parameter
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def initialize_rule(name, value, parameters)
|
35
|
+
rule_class = Rules.const_get(name.camelize)
|
36
|
+
rule_class.new(name, value, parameters)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module VanillaValidator
|
2
|
+
module Rules
|
3
|
+
class Required < BaseRule
|
4
|
+
def valid?
|
5
|
+
if value.nil?
|
6
|
+
return false
|
7
|
+
elsif value.class == String && value.strip == ''
|
8
|
+
return false
|
9
|
+
elsif value.class == Array && value.count < 1
|
10
|
+
return false
|
11
|
+
end
|
12
|
+
|
13
|
+
return true
|
14
|
+
end
|
15
|
+
|
16
|
+
def failure_message
|
17
|
+
I18n.t('required', attribute: attribute)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module VanillaValidator
|
2
|
+
module Rules
|
3
|
+
class RequiredIf < BaseRule
|
4
|
+
def valid?
|
5
|
+
other_rule = VanillaValidator::Rules::OtherRule.(VanillaValidator.raw_input, parameters)
|
6
|
+
|
7
|
+
other_rule.klass.valid? && required?
|
8
|
+
end
|
9
|
+
|
10
|
+
def failure_message
|
11
|
+
I18n.t("required_if", attribute: attribute, other: parameters[0].to_i, value: value)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module VanillaValidator
|
4
|
+
class ValueExtractor
|
5
|
+
# Public: Extracts data from a nested structure using a path.
|
6
|
+
#
|
7
|
+
# data - The nested data structure (Hash or Array) to extract data from.
|
8
|
+
# path - A string representing the path to the desired data, where
|
9
|
+
# individual segments are separated by periods ('.').
|
10
|
+
#
|
11
|
+
# Raises:
|
12
|
+
# - RuntimeError: If the path contains more than 5 segments, which
|
13
|
+
# exceeds the maximum allowed.
|
14
|
+
#
|
15
|
+
# Returns: The extracted data, or nil if the path does not lead to a valid value.
|
16
|
+
#
|
17
|
+
def self.get(data, path)
|
18
|
+
splited_path = path.to_s.split('.')
|
19
|
+
|
20
|
+
raise "Too many path segments (maximum allowed is 5)" if splited_path.length > 5
|
21
|
+
|
22
|
+
if path.include?("*")
|
23
|
+
self.get_at_wildcard_path(data, splited_path)
|
24
|
+
else
|
25
|
+
self.get_at_explicit_path(data, splited_path)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
# Private: Extracts data from a nested structure using an explicit path.
|
32
|
+
#
|
33
|
+
# data - The nested data structure (Hash or Array) to extract data from.
|
34
|
+
# path - An array of path segments.
|
35
|
+
#
|
36
|
+
# Returns: The extracted data, or nil if the path does not lead to a valid value.
|
37
|
+
#
|
38
|
+
def self.get_at_explicit_path(data, path)
|
39
|
+
data.dig(*steps_from(path))
|
40
|
+
end
|
41
|
+
|
42
|
+
# Private: Converts an array of path segments into appropriate data access steps.
|
43
|
+
#
|
44
|
+
# path - An array of path segments.
|
45
|
+
#
|
46
|
+
# Returns: An array of steps for data access (string keys or integer indices).
|
47
|
+
#
|
48
|
+
def self.steps_from path
|
49
|
+
path.map do |step|
|
50
|
+
step.match?(/\D/) ? step.to_s : step.to_i
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Private: Extracts data from a nested structure using a path that includes wildcard segments ('*').
|
55
|
+
#
|
56
|
+
# data - The nested data structure (Array) to extract data from.
|
57
|
+
# path - An array of path segments with wildcard(s).
|
58
|
+
# default - The value to return if the path does not lead to a valid value.
|
59
|
+
#
|
60
|
+
# Returns: The extracted data or the default value if the path does not lead to a valid value.
|
61
|
+
#
|
62
|
+
def self.get_at_wildcard_path(data, path, default = nil)
|
63
|
+
return data if path.empty?
|
64
|
+
|
65
|
+
path.each_with_index do |segment, index|
|
66
|
+
return data if segment.nil?
|
67
|
+
|
68
|
+
if segment.eql?("*")
|
69
|
+
rpath = path[index.next..-1] || []
|
70
|
+
|
71
|
+
unless data.is_a?(Array)
|
72
|
+
return default
|
73
|
+
end
|
74
|
+
|
75
|
+
result = data.map { |item| get_at_wildcard_path(item, rpath) }
|
76
|
+
|
77
|
+
return rpath.include?("*") ? result.flatten : result
|
78
|
+
end
|
79
|
+
|
80
|
+
if data.is_a?(Hash) && data.key?(segment)
|
81
|
+
data = data[segment]
|
82
|
+
elsif target.is_a?(Array) && ( Integer(segment) rescue false )
|
83
|
+
target = target[Integer(segment)]
|
84
|
+
else
|
85
|
+
return default
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
return data
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'i18n'
|
4
|
+
require 'uri'
|
5
|
+
require 'date'
|
6
|
+
require 'active_support/inflector'
|
7
|
+
require "zeitwerk"
|
8
|
+
|
9
|
+
# Configure Zeitwerk to load the classes and modules.
|
10
|
+
loader = Zeitwerk::Loader.for_gem
|
11
|
+
loader.ignore("#{__dir__}/vanilla_validator/railtie.rb")
|
12
|
+
loader.setup
|
13
|
+
|
14
|
+
# Add custom locales for I18n.
|
15
|
+
I18n.load_path += Dir[File.dirname(__FILE__) + "/locale/*.yml"]
|
16
|
+
|
17
|
+
# VanillaValidator is a Ruby module that provides validation functionality.
|
18
|
+
module VanillaValidator
|
19
|
+
extend self
|
20
|
+
|
21
|
+
# Extend the module with the methods from the Helpers module.
|
22
|
+
extend Helpers
|
23
|
+
|
24
|
+
# Public: Validate input data against a contract.
|
25
|
+
#
|
26
|
+
# input - The input data to be validated.
|
27
|
+
# contract - A set of validation rules defined as a Hash.
|
28
|
+
# options - A Hash of additional options for validation (optional).
|
29
|
+
#
|
30
|
+
# NOTE: The `@raw_input` instance variable is used in nested rules to prevent excessive parameter passing.
|
31
|
+
#
|
32
|
+
# Returns a Result object containing the validated attributes and any errors.
|
33
|
+
def validate(input, contract, options = {})
|
34
|
+
@raw_input = input.dup
|
35
|
+
|
36
|
+
errors = {}
|
37
|
+
validated = deep_clone_input(input)
|
38
|
+
stop_on_first_failure = options[:stop_on_first_failure]
|
39
|
+
|
40
|
+
contract.each do |attribute, term|
|
41
|
+
value = ValueExtractor.get(input, attribute)
|
42
|
+
rules = RuleParser.parse(term)
|
43
|
+
|
44
|
+
initialized_rules = rules.map do |rule|
|
45
|
+
initialize_rule(attribute, value, rule)
|
46
|
+
end
|
47
|
+
|
48
|
+
invalid_rules = initialized_rules.reject(&:valid?)
|
49
|
+
|
50
|
+
if invalid_rules.empty?
|
51
|
+
data_set(validated, attribute, value)
|
52
|
+
else
|
53
|
+
invalid_rules.each do |result|
|
54
|
+
(errors[attribute] ||= []) << result.failure_message
|
55
|
+
end
|
56
|
+
|
57
|
+
if stop_on_first_failure
|
58
|
+
validated_attributes = delete_missing_values(validated)
|
59
|
+
return Result.new(validated_attributes, errors)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Remove any missing or invalid attributes from the validated data.
|
65
|
+
validated_attributes = delete_missing_values(validated)
|
66
|
+
|
67
|
+
Result.new(validated_attributes, errors)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Public: Validate input data against a contract, stopping on the first failure.
|
71
|
+
#
|
72
|
+
# input - The input data to validate.
|
73
|
+
# contract - A contract specifying validation rules for input data.
|
74
|
+
#
|
75
|
+
# Returns: A Result object containing validated data and error messages.
|
76
|
+
#
|
77
|
+
def validate!(input, contract)
|
78
|
+
validate(input, contract, stop_on_first_failure: true)
|
79
|
+
end
|
80
|
+
|
81
|
+
def raw_input
|
82
|
+
@raw_input
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
# Private: Initialize a validation rule based on its name and parameters.
|
88
|
+
#
|
89
|
+
# attribute - The attribute being validated.
|
90
|
+
# value - The value to validate.
|
91
|
+
# rule - A rule object containing the name and parameters of the rule.
|
92
|
+
#
|
93
|
+
# Returns: An instance of the specific validation rule.
|
94
|
+
#
|
95
|
+
def initialize_rule(attribute, value, rule)
|
96
|
+
rule_class = Rules.const_get(rule.name.camelize)
|
97
|
+
rule_class.new(attribute, value, rule.parameters)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
loader.eager_load
|
102
|
+
|
103
|
+
require 'vanilla_validator/railtie' if defined? Rails
|
metadata
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vanilla_validator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.4.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Farid Mohammadi
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-01-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: i18n
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.2'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.2'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: zeitwerk
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2.5'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2.5'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: activesupport
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: Simple and easy to use validator inspired by Laravel Validator
|
70
|
+
email:
|
71
|
+
- 1997farid.mohammadi@gmail.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files:
|
75
|
+
- README.md
|
76
|
+
files:
|
77
|
+
- Gemfile
|
78
|
+
- Gemfile.lock
|
79
|
+
- README.md
|
80
|
+
- Rakefile
|
81
|
+
- lib/locale/en.yml
|
82
|
+
- lib/vanilla_validator.rb
|
83
|
+
- lib/vanilla_validator/helpers.rb
|
84
|
+
- lib/vanilla_validator/railtie.rb
|
85
|
+
- lib/vanilla_validator/result.rb
|
86
|
+
- lib/vanilla_validator/rule.rb
|
87
|
+
- lib/vanilla_validator/rule_parser.rb
|
88
|
+
- lib/vanilla_validator/rules/after.rb
|
89
|
+
- lib/vanilla_validator/rules/after_or_equal.rb
|
90
|
+
- lib/vanilla_validator/rules/base_rule.rb
|
91
|
+
- lib/vanilla_validator/rules/before.rb
|
92
|
+
- lib/vanilla_validator/rules/before_or_equal.rb
|
93
|
+
- lib/vanilla_validator/rules/block_rule.rb
|
94
|
+
- lib/vanilla_validator/rules/boolean.rb
|
95
|
+
- lib/vanilla_validator/rules/date.rb
|
96
|
+
- lib/vanilla_validator/rules/email.rb
|
97
|
+
- lib/vanilla_validator/rules/eq.rb
|
98
|
+
- lib/vanilla_validator/rules/falsy.rb
|
99
|
+
- lib/vanilla_validator/rules/gte.rb
|
100
|
+
- lib/vanilla_validator/rules/in.rb
|
101
|
+
- lib/vanilla_validator/rules/like.rb
|
102
|
+
- lib/vanilla_validator/rules/max.rb
|
103
|
+
- lib/vanilla_validator/rules/min.rb
|
104
|
+
- lib/vanilla_validator/rules/numeric.rb
|
105
|
+
- lib/vanilla_validator/rules/other_rule.rb
|
106
|
+
- lib/vanilla_validator/rules/required.rb
|
107
|
+
- lib/vanilla_validator/rules/required_if.rb
|
108
|
+
- lib/vanilla_validator/rules/url.rb
|
109
|
+
- lib/vanilla_validator/value_extractor.rb
|
110
|
+
- lib/vanilla_validator/version.rb
|
111
|
+
homepage: https://github.com/leurias/vanilla_validator
|
112
|
+
licenses: []
|
113
|
+
metadata:
|
114
|
+
allowed_push_host: https://rubygems.org
|
115
|
+
homepage_uri: https://github.com/leurias/vanilla_validator
|
116
|
+
source_code_uri: https://github.com/leurias/vanilla_validator
|
117
|
+
changelog_uri: https://github.com/leurias/vanilla_validator/CHANGELOG.md
|
118
|
+
post_install_message:
|
119
|
+
rdoc_options: []
|
120
|
+
require_paths:
|
121
|
+
- lib
|
122
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - ">="
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: 2.6.0
|
127
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
requirements: []
|
133
|
+
rubygems_version: 3.5.4
|
134
|
+
signing_key:
|
135
|
+
specification_version: 4
|
136
|
+
summary: Easy to use ruby validator
|
137
|
+
test_files: []
|