ruby-livr 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +45 -0
- data/Readme.md +119 -0
- data/lib/livr.rb +60 -0
- data/lib/livr/aliased_rule.rb +26 -0
- data/lib/livr/rule.rb +21 -0
- data/lib/livr/rules/common.rb +35 -0
- data/lib/livr/rules/meta.rb +200 -0
- data/lib/livr/rules/modifiers.rb +68 -0
- data/lib/livr/rules/numeric.rb +136 -0
- data/lib/livr/rules/special.rb +65 -0
- data/lib/livr/rules/string.rb +150 -0
- data/lib/livr/validator.rb +134 -0
- data/ruby-livr.gemspec +19 -0
- data/spec/01-test_suite_spec.rb +34 -0
- data/spec/02-aliases_spec.rb +21 -0
- data/spec/03-auto_trim_spec.rb +56 -0
- data/spec/04-custom_filters_spec.rb +54 -0
- data/spec/05-rules_replacement_spec.rb +67 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/test_suite/aliases_negative/01-adult_age/aliases.json +12 -0
- data/spec/test_suite/aliases_negative/01-adult_age/errors.json +6 -0
- data/spec/test_suite/aliases_negative/01-adult_age/input.json +11 -0
- data/spec/test_suite/aliases_negative/01-adult_age/rules.json +10 -0
- data/spec/test_suite/aliases_negative/02-address/aliases.json +20 -0
- data/spec/test_suite/aliases_negative/02-address/errors.json +8 -0
- data/spec/test_suite/aliases_negative/02-address/input.json +13 -0
- data/spec/test_suite/aliases_negative/02-address/rules.json +4 -0
- data/spec/test_suite/aliases_negative/03-adult_age_in_user/aliases.json +31 -0
- data/spec/test_suite/aliases_negative/03-adult_age_in_user/errors.json +8 -0
- data/spec/test_suite/aliases_negative/03-adult_age_in_user/input.json +14 -0
- data/spec/test_suite/aliases_negative/03-adult_age_in_user/rules.json +4 -0
- data/spec/test_suite/aliases_positive/01-adult_age/aliases.json +12 -0
- data/spec/test_suite/aliases_positive/01-adult_age/input.json +11 -0
- data/spec/test_suite/aliases_positive/01-adult_age/output.json +10 -0
- data/spec/test_suite/aliases_positive/01-adult_age/rules.json +10 -0
- data/spec/test_suite/aliases_positive/02-address/aliases.json +20 -0
- data/spec/test_suite/aliases_positive/02-address/input.json +13 -0
- data/spec/test_suite/aliases_positive/02-address/output.json +12 -0
- data/spec/test_suite/aliases_positive/02-address/rules.json +4 -0
- data/spec/test_suite/aliases_positive/03-adult_age_in_user/aliases.json +31 -0
- data/spec/test_suite/aliases_positive/03-adult_age_in_user/input.json +14 -0
- data/spec/test_suite/aliases_positive/03-adult_age_in_user/output.json +12 -0
- data/spec/test_suite/aliases_positive/03-adult_age_in_user/rules.json +4 -0
- data/spec/test_suite/negative/01-required/errors.json +5 -0
- data/spec/test_suite/negative/01-required/input.json +10 -0
- data/spec/test_suite/negative/01-required/rules.json +10 -0
- data/spec/test_suite/negative/02-not_empty/errors.json +3 -0
- data/spec/test_suite/negative/02-not_empty/input.json +10 -0
- data/spec/test_suite/negative/02-not_empty/rules.json +10 -0
- data/spec/test_suite/negative/03-one_of/errors.json +11 -0
- data/spec/test_suite/negative/03-one_of/input.json +12 -0
- data/spec/test_suite/negative/03-one_of/rules.json +11 -0
- data/spec/test_suite/negative/04-min_length/errors.json +10 -0
- data/spec/test_suite/negative/04-min_length/input.json +12 -0
- data/spec/test_suite/negative/04-min_length/rules.json +11 -0
- data/spec/test_suite/negative/05-max_length/errors.json +10 -0
- data/spec/test_suite/negative/05-max_length/input.json +12 -0
- data/spec/test_suite/negative/05-max_length/rules.json +11 -0
- data/spec/test_suite/negative/06-length_equal/errors.json +10 -0
- data/spec/test_suite/negative/06-length_equal/input.json +12 -0
- data/spec/test_suite/negative/06-length_equal/rules.json +11 -0
- data/spec/test_suite/negative/07-length_between/errors.json +10 -0
- data/spec/test_suite/negative/07-length_between/input.json +12 -0
- data/spec/test_suite/negative/07-length_between/rules.json +11 -0
- data/spec/test_suite/negative/08-like/errors.json +11 -0
- data/spec/test_suite/negative/08-like/input.json +14 -0
- data/spec/test_suite/negative/08-like/rules.json +12 -0
- data/spec/test_suite/negative/09-integer/errors.json +11 -0
- data/spec/test_suite/negative/09-integer/input.json +13 -0
- data/spec/test_suite/negative/09-integer/rules.json +12 -0
- data/spec/test_suite/negative/10-positive_integer/errors.json +11 -0
- data/spec/test_suite/negative/10-positive_integer/input.json +13 -0
- data/spec/test_suite/negative/10-positive_integer/rules.json +12 -0
- data/spec/test_suite/negative/11-decimal/errors.json +11 -0
- data/spec/test_suite/negative/11-decimal/input.json +13 -0
- data/spec/test_suite/negative/11-decimal/rules.json +12 -0
- data/spec/test_suite/negative/12-positive_decimal/errors.json +11 -0
- data/spec/test_suite/negative/12-positive_decimal/input.json +13 -0
- data/spec/test_suite/negative/12-positive_decimal/rules.json +12 -0
- data/spec/test_suite/negative/13-max_number/errors.json +10 -0
- data/spec/test_suite/negative/13-max_number/input.json +12 -0
- data/spec/test_suite/negative/13-max_number/rules.json +11 -0
- data/spec/test_suite/negative/14-min_number/errors.json +11 -0
- data/spec/test_suite/negative/14-min_number/input.json +13 -0
- data/spec/test_suite/negative/14-min_number/rules.json +12 -0
- data/spec/test_suite/negative/15-number_beetween/errors.json +12 -0
- data/spec/test_suite/negative/15-number_beetween/input.json +14 -0
- data/spec/test_suite/negative/15-number_beetween/rules.json +13 -0
- data/spec/test_suite/negative/16-email/errors.json +12 -0
- data/spec/test_suite/negative/16-email/input.json +14 -0
- data/spec/test_suite/negative/16-email/rules.json +13 -0
- data/spec/test_suite/negative/17-equal_to_field/errors.json +10 -0
- data/spec/test_suite/negative/17-equal_to_field/input.json +12 -0
- data/spec/test_suite/negative/17-equal_to_field/rules.json +11 -0
- data/spec/test_suite/negative/18-nested_object/errors.json +9 -0
- data/spec/test_suite/negative/18-nested_object/input.json +9 -0
- data/spec/test_suite/negative/18-nested_object/rules.json +9 -0
- data/spec/test_suite/negative/19-list_of/errors.json +6 -0
- data/spec/test_suite/negative/19-list_of/input.json +6 -0
- data/spec/test_suite/negative/19-list_of/rules.json +14 -0
- data/spec/test_suite/negative/20-list_of_objects/errors.json +14 -0
- data/spec/test_suite/negative/20-list_of_objects/input.json +18 -0
- data/spec/test_suite/negative/20-list_of_objects/rules.json +7 -0
- data/spec/test_suite/negative/21-list_of_different_objects/errors.json +17 -0
- data/spec/test_suite/negative/21-list_of_different_objects/input.json +26 -0
- data/spec/test_suite/negative/21-list_of_different_objects/rules.json +17 -0
- data/spec/test_suite/negative/22-not_empty_list/errors.json +7 -0
- data/spec/test_suite/negative/22-not_empty_list/input.json +6 -0
- data/spec/test_suite/negative/22-not_empty_list/rules.json +7 -0
- data/spec/test_suite/negative/23-url/errors.json +10 -0
- data/spec/test_suite/negative/23-url/input.json +12 -0
- data/spec/test_suite/negative/23-url/rules.json +11 -0
- data/spec/test_suite/negative/24-iso_date/errors.json +11 -0
- data/spec/test_suite/negative/24-iso_date/input.json +13 -0
- data/spec/test_suite/negative/24-iso_date/rules.json +12 -0
- data/spec/test_suite/negative/25-eq/errors.json +13 -0
- data/spec/test_suite/negative/25-eq/input.json +14 -0
- data/spec/test_suite/negative/25-eq/rules.json +13 -0
- data/spec/test_suite/negative/26-string/errors.json +6 -0
- data/spec/test_suite/negative/26-string/input.json +6 -0
- data/spec/test_suite/negative/26-string/rules.json +6 -0
- data/spec/test_suite/negative/27-any_object/errors.json +6 -0
- data/spec/test_suite/negative/27-any_object/input.json +6 -0
- data/spec/test_suite/negative/27-any_object/rules.json +6 -0
- data/spec/test_suite/negative/28-variable_object/errors.json +15 -0
- data/spec/test_suite/negative/28-variable_object/input.json +24 -0
- data/spec/test_suite/negative/28-variable_object/rules.json +77 -0
- data/spec/test_suite/negative/29-or/errors.json +14 -0
- data/spec/test_suite/negative/29-or/input.json +20 -0
- data/spec/test_suite/negative/29-or/rules.json +19 -0
- data/spec/test_suite/positive/01-required/input.json +7 -0
- data/spec/test_suite/positive/01-required/output.json +6 -0
- data/spec/test_suite/positive/01-required/rules.json +6 -0
- data/spec/test_suite/positive/02-not_empty/input.json +6 -0
- data/spec/test_suite/positive/02-not_empty/output.json +5 -0
- data/spec/test_suite/positive/02-not_empty/rules.json +6 -0
- data/spec/test_suite/positive/03-one_of/input.json +11 -0
- data/spec/test_suite/positive/03-one_of/output.json +10 -0
- data/spec/test_suite/positive/03-one_of/rules.json +10 -0
- data/spec/test_suite/positive/04-min_length/input.json +8 -0
- data/spec/test_suite/positive/04-min_length/output.json +7 -0
- data/spec/test_suite/positive/04-min_length/rules.json +8 -0
- data/spec/test_suite/positive/05-max_length/input.json +9 -0
- data/spec/test_suite/positive/05-max_length/output.json +8 -0
- data/spec/test_suite/positive/05-max_length/rules.json +9 -0
- data/spec/test_suite/positive/06-length_equal/input.json +8 -0
- data/spec/test_suite/positive/06-length_equal/output.json +7 -0
- data/spec/test_suite/positive/06-length_equal/rules.json +8 -0
- data/spec/test_suite/positive/07-length_between/input.json +9 -0
- data/spec/test_suite/positive/07-length_between/output.json +8 -0
- data/spec/test_suite/positive/07-length_between/rules.json +9 -0
- data/spec/test_suite/positive/08-like/input.json +8 -0
- data/spec/test_suite/positive/08-like/output.json +7 -0
- data/spec/test_suite/positive/08-like/rules.json +8 -0
- data/spec/test_suite/positive/09-integer/input.json +7 -0
- data/spec/test_suite/positive/09-integer/output.json +6 -0
- data/spec/test_suite/positive/09-integer/rules.json +7 -0
- data/spec/test_suite/positive/10-positive_integer/input.json +7 -0
- data/spec/test_suite/positive/10-positive_integer/output.json +6 -0
- data/spec/test_suite/positive/10-positive_integer/rules.json +6 -0
- data/spec/test_suite/positive/11-decimal/input.json +8 -0
- data/spec/test_suite/positive/11-decimal/output.json +7 -0
- data/spec/test_suite/positive/11-decimal/rules.json +7 -0
- data/spec/test_suite/positive/12-positive_decimal/input.json +8 -0
- data/spec/test_suite/positive/12-positive_decimal/output.json +7 -0
- data/spec/test_suite/positive/12-positive_decimal/rules.json +7 -0
- data/spec/test_suite/positive/13-max_number/input.json +7 -0
- data/spec/test_suite/positive/13-max_number/output.json +6 -0
- data/spec/test_suite/positive/13-max_number/rules.json +6 -0
- data/spec/test_suite/positive/14-min_number/input.json +7 -0
- data/spec/test_suite/positive/14-min_number/output.json +6 -0
- data/spec/test_suite/positive/14-min_number/rules.json +6 -0
- data/spec/test_suite/positive/15-number_between/input.json +8 -0
- data/spec/test_suite/positive/15-number_between/output.json +7 -0
- data/spec/test_suite/positive/15-number_between/rules.json +7 -0
- data/spec/test_suite/positive/16-email/input.json +7 -0
- data/spec/test_suite/positive/16-email/output.json +6 -0
- data/spec/test_suite/positive/16-email/rules.json +6 -0
- data/spec/test_suite/positive/17-equal_to_field/input.json +7 -0
- data/spec/test_suite/positive/17-equal_to_field/output.json +6 -0
- data/spec/test_suite/positive/17-equal_to_field/rules.json +6 -0
- data/spec/test_suite/positive/18-nested_object/input.json +15 -0
- data/spec/test_suite/positive/18-nested_object/output.json +12 -0
- data/spec/test_suite/positive/18-nested_object/rules.json +13 -0
- data/spec/test_suite/positive/19-list_of/input.json +7 -0
- data/spec/test_suite/positive/19-list_of/output.json +7 -0
- data/spec/test_suite/positive/19-list_of/rules.json +15 -0
- data/spec/test_suite/positive/20-list_of_objects/input.json +17 -0
- data/spec/test_suite/positive/20-list_of_objects/output.json +17 -0
- data/spec/test_suite/positive/20-list_of_objects/rules.json +10 -0
- data/spec/test_suite/positive/21-list_of_different_objects/input.json +22 -0
- data/spec/test_suite/positive/21-list_of_different_objects/output.json +21 -0
- data/spec/test_suite/positive/21-list_of_different_objects/rules.json +27 -0
- data/spec/test_suite/positive/22-not_empty_list/input.json +6 -0
- data/spec/test_suite/positive/22-not_empty_list/output.json +5 -0
- data/spec/test_suite/positive/22-not_empty_list/rules.json +5 -0
- data/spec/test_suite/positive/23-url/input.json +7 -0
- data/spec/test_suite/positive/23-url/output.json +6 -0
- data/spec/test_suite/positive/23-url/rules.json +6 -0
- data/spec/test_suite/positive/24-iso_date/input.json +9 -0
- data/spec/test_suite/positive/24-iso_date/output.json +8 -0
- data/spec/test_suite/positive/24-iso_date/rules.json +8 -0
- data/spec/test_suite/positive/25-eq/input.json +10 -0
- data/spec/test_suite/positive/25-eq/output.json +9 -0
- data/spec/test_suite/positive/25-eq/rules.json +9 -0
- data/spec/test_suite/positive/26-string/input.json +8 -0
- data/spec/test_suite/positive/26-string/output.json +7 -0
- data/spec/test_suite/positive/26-string/rules.json +7 -0
- data/spec/test_suite/positive/27-any_object/input.json +6 -0
- data/spec/test_suite/positive/27-any_object/output.json +6 -0
- data/spec/test_suite/positive/27-any_object/rules.json +7 -0
- data/spec/test_suite/positive/28-variable_object/input.json +19 -0
- data/spec/test_suite/positive/28-variable_object/output.json +18 -0
- data/spec/test_suite/positive/28-variable_object/rules.json +47 -0
- data/spec/test_suite/positive/29-or/input.json +25 -0
- data/spec/test_suite/positive/29-or/output.json +24 -0
- data/spec/test_suite/positive/29-or/rules.json +24 -0
- data/spec/test_suite/positive/30-trim/input.json +7 -0
- data/spec/test_suite/positive/30-trim/output.json +7 -0
- data/spec/test_suite/positive/30-trim/rules.json +7 -0
- data/spec/test_suite/positive/31-to_lc/input.json +8 -0
- data/spec/test_suite/positive/31-to_lc/output.json +8 -0
- data/spec/test_suite/positive/31-to_lc/rules.json +8 -0
- data/spec/test_suite/positive/32-to_uc/input.json +7 -0
- data/spec/test_suite/positive/32-to_uc/output.json +7 -0
- data/spec/test_suite/positive/32-to_uc/rules.json +7 -0
- data/spec/test_suite/positive/33-remove/input.json +5 -0
- data/spec/test_suite/positive/33-remove/output.json +5 -0
- data/spec/test_suite/positive/33-remove/rules.json +7 -0
- data/spec/test_suite/positive/34-leave_only/input.json +5 -0
- data/spec/test_suite/positive/34-leave_only/output.json +5 -0
- data/spec/test_suite/positive/34-leave_only/rules.json +7 -0
- data/spec/test_suite/positive/35-default/input.json +10 -0
- data/spec/test_suite/positive/35-default/output.json +12 -0
- data/spec/test_suite/positive/35-default/rules.json +12 -0
- metadata +532 -0
@@ -0,0 +1,68 @@
|
|
1
|
+
module LIVR
|
2
|
+
module Rules
|
3
|
+
module Modifiers
|
4
|
+
class Default < Rule
|
5
|
+
def initialize(default_value)
|
6
|
+
@default_value = default_value
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(value, user_data, field_results)
|
10
|
+
if is_no_value(value)
|
11
|
+
field_results << @default_value
|
12
|
+
end
|
13
|
+
return
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class Trim < Rule
|
18
|
+
def call(value, user_data, field_results)
|
19
|
+
return if is_no_value(value) || value.is_a?(Hash)
|
20
|
+
field_results << value.to_s.mb_chars.strip
|
21
|
+
return
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class ToLc < Rule
|
26
|
+
def call(value, user_data, field_results)
|
27
|
+
return if is_no_value(value) || value.is_a?(Hash)
|
28
|
+
field_results << value.to_s.mb_chars.downcase
|
29
|
+
return
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class ToUc < Rule
|
34
|
+
def call(value, user_data, field_results)
|
35
|
+
return if is_no_value(value) || value.is_a?(Hash)
|
36
|
+
field_results << value.to_s.mb_chars.upcase
|
37
|
+
return
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class Remove < Rule
|
42
|
+
def initialize(chars)
|
43
|
+
@chars = chars
|
44
|
+
@re = Regexp.compile("[#{Regexp.quote(@chars)}]")
|
45
|
+
end
|
46
|
+
|
47
|
+
def call(value, user_data, field_results)
|
48
|
+
return if is_no_value(value) || value.is_a?(Hash)
|
49
|
+
field_results << value.to_s.mb_chars.gsub(@re, '')
|
50
|
+
return
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class LeaveOnly < Rule
|
55
|
+
def initialize(chars)
|
56
|
+
@chars = chars
|
57
|
+
@re = Regexp.compile("[^#{Regexp.quote(@chars)}]")
|
58
|
+
end
|
59
|
+
|
60
|
+
def call(value, user_data, field_results)
|
61
|
+
return if is_no_value(value) || value.is_a?(Hash)
|
62
|
+
field_results << value.to_s.mb_chars.gsub(@re, '')
|
63
|
+
return
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
module LIVR
|
2
|
+
module Rules
|
3
|
+
module Numeric
|
4
|
+
|
5
|
+
class Integer < Rule
|
6
|
+
def call(value, user_data, field_results)
|
7
|
+
return if is_no_value(value)
|
8
|
+
return 'FORMAT_ERROR' if !is_primitive(value)
|
9
|
+
|
10
|
+
value_int = Integer(value.to_s) rescue nil
|
11
|
+
if value_int.nil?
|
12
|
+
return "NOT_INTEGER"
|
13
|
+
end
|
14
|
+
|
15
|
+
field_results << value_int
|
16
|
+
return
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
class PositiveInteger < Rule
|
22
|
+
def call(value, user_data, field_results)
|
23
|
+
return if is_no_value(value)
|
24
|
+
return 'FORMAT_ERROR' if !is_primitive(value)
|
25
|
+
|
26
|
+
value_int = Integer(value.to_s) rescue nil
|
27
|
+
|
28
|
+
return "NOT_POSITIVE_INTEGER" if value_int.nil?
|
29
|
+
return "NOT_POSITIVE_INTEGER" unless value_int.positive?
|
30
|
+
|
31
|
+
field_results << value_int
|
32
|
+
return
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class Decimal < Rule
|
37
|
+
def call(value, user_data, field_results)
|
38
|
+
return if is_no_value(value)
|
39
|
+
return 'FORMAT_ERROR' if !is_primitive(value)
|
40
|
+
|
41
|
+
value_int = Float(value.to_s) rescue nil
|
42
|
+
return "NOT_DECIMAL" if value_int.nil?
|
43
|
+
|
44
|
+
field_results << value_int
|
45
|
+
return
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
class PositiveDecimal < Rule
|
51
|
+
def call(value, user_data, field_results)
|
52
|
+
return if is_no_value(value)
|
53
|
+
return 'FORMAT_ERROR' if !is_primitive(value)
|
54
|
+
|
55
|
+
value_float = Float(value.to_s) rescue nil
|
56
|
+
return "NOT_POSITIVE_DECIMAL" if value_float.nil?
|
57
|
+
return "NOT_POSITIVE_DECIMAL" unless value_float.positive?
|
58
|
+
|
59
|
+
field_results << value_float
|
60
|
+
return
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class MaxNumber < Rule
|
65
|
+
def initialize(max_number)
|
66
|
+
@max_number = max_number
|
67
|
+
end
|
68
|
+
|
69
|
+
def call(value, user_data, field_results)
|
70
|
+
return if is_no_value(value)
|
71
|
+
return 'FORMAT_ERROR' if !is_primitive(value)
|
72
|
+
|
73
|
+
value = Float(value.to_s) rescue nil
|
74
|
+
if value.nil?
|
75
|
+
return "NOT_NUMBER"
|
76
|
+
end
|
77
|
+
|
78
|
+
if value > @max_number
|
79
|
+
return "TOO_HIGH"
|
80
|
+
else
|
81
|
+
field_results << value
|
82
|
+
return
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
class MinNumber < Rule
|
88
|
+
def initialize(min_number)
|
89
|
+
@min_number = min_number
|
90
|
+
end
|
91
|
+
|
92
|
+
def call(value, user_data, field_results)
|
93
|
+
return if is_no_value(value)
|
94
|
+
return 'FORMAT_ERROR' if !is_primitive(value)
|
95
|
+
|
96
|
+
value = Float(value.to_s) rescue nil
|
97
|
+
if value.nil?
|
98
|
+
return "NOT_NUMBER"
|
99
|
+
end
|
100
|
+
|
101
|
+
if value < @min_number
|
102
|
+
return "TOO_LOW"
|
103
|
+
else
|
104
|
+
field_results << value
|
105
|
+
return
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
class NumberBetween < Rule
|
111
|
+
def initialize(min_number, max_number)
|
112
|
+
@min_number = min_number
|
113
|
+
@max_number = max_number
|
114
|
+
end
|
115
|
+
|
116
|
+
def call(value, user_data, field_results)
|
117
|
+
return if is_no_value(value)
|
118
|
+
return 'FORMAT_ERROR' if !is_primitive(value)
|
119
|
+
|
120
|
+
value = Float(value.to_s) rescue nil
|
121
|
+
if value.nil?
|
122
|
+
return "NOT_NUMBER"
|
123
|
+
end
|
124
|
+
|
125
|
+
|
126
|
+
return "TOO_LOW" if value < @min_number
|
127
|
+
return "TOO_HIGH" if value > @max_number
|
128
|
+
|
129
|
+
field_results << value
|
130
|
+
return
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module LIVR
|
2
|
+
module Rules
|
3
|
+
module Special
|
4
|
+
|
5
|
+
class Email < Rule
|
6
|
+
def call(value, user_data, field_results)
|
7
|
+
return if is_no_value(value)
|
8
|
+
return 'FORMAT_ERROR' if !is_primitive(value)
|
9
|
+
|
10
|
+
value = value.to_s
|
11
|
+
email_re = /^([\w\-_+]+(?:\.[\w\-_+]+)*)@((?:[\w\-]+\.)*\w[\w\-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i
|
12
|
+
return "WRONG_EMAIL" unless email_re.match(value)
|
13
|
+
return "WRONG_EMAIL" if /\@.*\@/.match(value)
|
14
|
+
return "WRONG_EMAIL" if /\@.*_/.match(value)
|
15
|
+
return
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class EqualToField < Rule
|
20
|
+
def initialize(field)
|
21
|
+
@field = field
|
22
|
+
end
|
23
|
+
|
24
|
+
def call(value, user_data, field_results)
|
25
|
+
return if is_no_value(value)
|
26
|
+
return 'FORMAT_ERROR' if !is_primitive(value)
|
27
|
+
|
28
|
+
return "FIELDS_NOT_EQUAL" if value != user_data[@field]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class Url < Rule
|
33
|
+
URL_RE_STR = '^(?:(?:http|https)://)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[0-1]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))\\.?|localhost)(?::\\d{2,5})?(?:[/?#]\\S*)?$'
|
34
|
+
URL_RE = Regexp.compile(URL_RE_STR, "i")
|
35
|
+
MAX_URL_LENGTH = 2083
|
36
|
+
|
37
|
+
def call(value, user_data, field_results)
|
38
|
+
return if is_no_value(value)
|
39
|
+
return 'FORMAT_ERROR' if !is_primitive(value)
|
40
|
+
|
41
|
+
if value.length < MAX_URL_LENGTH && URL_RE.match(value)
|
42
|
+
return
|
43
|
+
else
|
44
|
+
'WRONG_URL'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class IsoDate < Rule
|
50
|
+
def call(value, user_data, field_results)
|
51
|
+
return if is_no_value(value)
|
52
|
+
return 'FORMAT_ERROR' if !is_primitive(value)
|
53
|
+
|
54
|
+
return "WRONG_DATE" unless value.length == "YYYY-MM-DD".length
|
55
|
+
|
56
|
+
date = Date.strptime(value, '%Y-%m-%d') rescue nil
|
57
|
+
unless date
|
58
|
+
return "WRONG_DATE"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
module LIVR
|
2
|
+
module Rules
|
3
|
+
module String
|
4
|
+
|
5
|
+
class String < Rule
|
6
|
+
def call(value, user_data, field_results)
|
7
|
+
return if value.in? [nil, ""]
|
8
|
+
return 'FORMAT_ERROR' unless is_primitive(value)
|
9
|
+
|
10
|
+
field_results << value.to_s
|
11
|
+
|
12
|
+
return nil
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Eq < Rule
|
17
|
+
def initialize(allowed_value)
|
18
|
+
@allowed_value = allowed_value
|
19
|
+
end
|
20
|
+
|
21
|
+
def call(value, user_data, field_results)
|
22
|
+
return if is_no_value(value)
|
23
|
+
return 'FORMAT_ERROR' unless is_primitive(value)
|
24
|
+
|
25
|
+
if value.to_s == @allowed_value.to_s
|
26
|
+
field_results << @allowed_value
|
27
|
+
return
|
28
|
+
end
|
29
|
+
|
30
|
+
return 'NOT_ALLOWED_VALUE'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class OneOf < Rule
|
35
|
+
def initialize(*allowed_values)
|
36
|
+
@allowed_values = allowed_values.flatten
|
37
|
+
end
|
38
|
+
|
39
|
+
def call(value, user_data, field_results)
|
40
|
+
return if is_no_value(value)
|
41
|
+
return 'FORMAT_ERROR' unless is_primitive(value)
|
42
|
+
|
43
|
+
@allowed_values.each do |allowed_value|
|
44
|
+
if allowed_value.to_s == value.to_s
|
45
|
+
field_results << allowed_value
|
46
|
+
return
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
return 'NOT_ALLOWED_VALUE'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class MaxLength < Rule
|
55
|
+
def initialize(max_length)
|
56
|
+
@max_length = max_length
|
57
|
+
end
|
58
|
+
|
59
|
+
def call(value, user_data, field_results)
|
60
|
+
return if value.in? [nil, ""]
|
61
|
+
return 'FORMAT_ERROR' unless is_primitive(value)
|
62
|
+
|
63
|
+
return 'TOO_LONG' if value.to_s.length > @max_length
|
64
|
+
field_results << value.to_s
|
65
|
+
return
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class MinLength < Rule
|
70
|
+
def initialize(min_length)
|
71
|
+
@min_length = min_length
|
72
|
+
end
|
73
|
+
|
74
|
+
def call(value, user_data, field_results)
|
75
|
+
return if is_no_value(value)
|
76
|
+
return 'FORMAT_ERROR' unless is_primitive(value)
|
77
|
+
if value.to_s.length < @min_length
|
78
|
+
return 'TOO_SHORT'
|
79
|
+
end
|
80
|
+
|
81
|
+
field_results << value.to_s
|
82
|
+
return
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class LengthEqual < Rule
|
87
|
+
def initialize(length)
|
88
|
+
@length = length
|
89
|
+
end
|
90
|
+
|
91
|
+
def call(value, user_data, field_results)
|
92
|
+
return if value.in? [nil, ""]
|
93
|
+
return 'FORMAT_ERROR' unless is_primitive(value)
|
94
|
+
|
95
|
+
value = value.to_s
|
96
|
+
return 'TOO_SHORT' if value.length < @length
|
97
|
+
return 'TOO_LONG' if value.length > @length
|
98
|
+
|
99
|
+
field_results << value
|
100
|
+
|
101
|
+
return
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
class LengthBetween < Rule
|
106
|
+
def initialize(min_length, max_length)
|
107
|
+
@min_length = min_length
|
108
|
+
@max_length = max_length
|
109
|
+
end
|
110
|
+
|
111
|
+
def call(value, user_data, field_results)
|
112
|
+
return if value.in? [nil, ""]
|
113
|
+
return 'FORMAT_ERROR' unless is_primitive(value)
|
114
|
+
|
115
|
+
value = value.to_s
|
116
|
+
return 'TOO_SHORT' if value.length < @min_length
|
117
|
+
return 'TOO_LONG' if value.length > @max_length
|
118
|
+
|
119
|
+
field_results << value
|
120
|
+
|
121
|
+
return
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
class Like < Rule
|
126
|
+
def initialize(re_str, flags=nil)
|
127
|
+
@re_str = re_str
|
128
|
+
@flags = flags
|
129
|
+
end
|
130
|
+
|
131
|
+
def call(value, user_data, field_results)
|
132
|
+
return if value.in? [nil, ""]
|
133
|
+
return 'FORMAT_ERROR' unless is_primitive(value)
|
134
|
+
|
135
|
+
value = value.to_s
|
136
|
+
regexp = Regexp.compile(@re_str, @flags)
|
137
|
+
|
138
|
+
unless regexp.match(value)
|
139
|
+
return 'WRONG_FORMAT'
|
140
|
+
end
|
141
|
+
|
142
|
+
field_results << value
|
143
|
+
|
144
|
+
return
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
module LIVR
|
2
|
+
class Validator
|
3
|
+
def initialize(rules, is_auto_trim=false)
|
4
|
+
@rules = rules
|
5
|
+
@is_prepared = false
|
6
|
+
@validator_builders = {}
|
7
|
+
@validators = {}
|
8
|
+
@is_auto_trim = is_auto_trim
|
9
|
+
|
10
|
+
register_default_rules
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.register_default_rules(rules)
|
14
|
+
@@default_rules ||= {}
|
15
|
+
@@default_rules.merge!(rules.with_indifferent_access)
|
16
|
+
end
|
17
|
+
|
18
|
+
def register_aliased_rule(_alias)
|
19
|
+
register_rules( _alias["name"] => AliasedRule.new(_alias) )
|
20
|
+
end
|
21
|
+
|
22
|
+
def prepare
|
23
|
+
@rules.each do |field, field_rules|
|
24
|
+
field_rules = Array.wrap(field_rules)
|
25
|
+
@validators[field] = field_rules.map do |field_rule|
|
26
|
+
rule_name, rule_args = parse_rule(field_rule)
|
27
|
+
build_validator(rule_name, rule_args)
|
28
|
+
end
|
29
|
+
@is_prepared = true
|
30
|
+
end
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
def validate(user_data)
|
35
|
+
prepare unless @is_prepared
|
36
|
+
|
37
|
+
unless user_data.is_a?(Hash)
|
38
|
+
@errors = 'FORMAT_ERROR'
|
39
|
+
return
|
40
|
+
end
|
41
|
+
|
42
|
+
if @is_auto_trim
|
43
|
+
user_data = auto_trim(user_data)
|
44
|
+
end
|
45
|
+
|
46
|
+
@result = {}
|
47
|
+
@errors = {}
|
48
|
+
|
49
|
+
@validators.each do |field, validators|
|
50
|
+
next if validators.blank?
|
51
|
+
next if !@rules.has_key?(field)
|
52
|
+
|
53
|
+
value = user_data[field]
|
54
|
+
validators.each do |validator|
|
55
|
+
field_results = []
|
56
|
+
field_value = @result.fetch(field, value)
|
57
|
+
error_code = validator.call(field_value, user_data, field_results)
|
58
|
+
|
59
|
+
if error_code
|
60
|
+
@errors[field] = error_code
|
61
|
+
break
|
62
|
+
elsif field_results.present?
|
63
|
+
@result[field] = field_results.first
|
64
|
+
elsif user_data.has_key?(field) && !@result.has_key?(field)
|
65
|
+
@result[field] = value
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
if @errors.present?
|
71
|
+
return false
|
72
|
+
else
|
73
|
+
@errors = nil
|
74
|
+
return @result
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def register_rules(rules)
|
79
|
+
@validator_builders.merge!(rules)
|
80
|
+
self
|
81
|
+
end
|
82
|
+
|
83
|
+
def get_errors
|
84
|
+
@errors
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def register_default_rules
|
90
|
+
register_rules(@@default_rules || [])
|
91
|
+
end
|
92
|
+
|
93
|
+
def parse_rule(livr_rule)
|
94
|
+
name = nil
|
95
|
+
args = nil
|
96
|
+
|
97
|
+
case livr_rule
|
98
|
+
when Hash
|
99
|
+
name = livr_rule.keys.first
|
100
|
+
args = Array.wrap(livr_rule[name])
|
101
|
+
else
|
102
|
+
name = livr_rule
|
103
|
+
args = []
|
104
|
+
end
|
105
|
+
|
106
|
+
[ name, args ]
|
107
|
+
end
|
108
|
+
|
109
|
+
def build_validator(name, args)
|
110
|
+
if @validator_builders[name].blank?
|
111
|
+
raise "Rule ['#{name}'] not registered"
|
112
|
+
end
|
113
|
+
@validator_builders[name].new(*args)
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
def auto_trim(user_data)
|
119
|
+
case user_data
|
120
|
+
when String
|
121
|
+
user_data.strip
|
122
|
+
when Array
|
123
|
+
user_data.map{|v| auto_trim(v) }
|
124
|
+
when Hash
|
125
|
+
user_data.each do |key, value|
|
126
|
+
user_data[key] = auto_trim(value)
|
127
|
+
end
|
128
|
+
else
|
129
|
+
user_data
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
end
|