livr 0.0.2

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.
Files changed (203) hide show
  1. checksums.yaml +7 -0
  2. data/.travis.yml +6 -0
  3. data/Gemfile +2 -0
  4. data/README.md +240 -0
  5. data/Rakefile +9 -0
  6. data/lib/LIVR.rb +221 -0
  7. data/lib/LIVR/Rules/Common.rb +21 -0
  8. data/lib/LIVR/Rules/Filters.rb +43 -0
  9. data/lib/LIVR/Rules/Helpers.rb +126 -0
  10. data/lib/LIVR/Rules/Numerics.rb +63 -0
  11. data/lib/LIVR/Rules/Special.rb +55 -0
  12. data/lib/LIVR/Rules/Strings.rb +71 -0
  13. data/lib/LIVR/Util.rb +6 -0
  14. data/livr.gemspec +29 -0
  15. data/test/01-test_suite.rb +77 -0
  16. data/test/02-test_auto_trim.rb +55 -0
  17. data/test/03-test_rules_registration.rb +63 -0
  18. data/test/04-test_custom_filters.rb +44 -0
  19. data/test/test_helper.rb +6 -0
  20. data/test/test_suite/aliases_negative/01-adult_age/aliases.json +12 -0
  21. data/test/test_suite/aliases_negative/01-adult_age/errors.json +6 -0
  22. data/test/test_suite/aliases_negative/01-adult_age/input.json +11 -0
  23. data/test/test_suite/aliases_negative/01-adult_age/rules.json +10 -0
  24. data/test/test_suite/aliases_negative/02-address/aliases.json +20 -0
  25. data/test/test_suite/aliases_negative/02-address/errors.json +8 -0
  26. data/test/test_suite/aliases_negative/02-address/input.json +13 -0
  27. data/test/test_suite/aliases_negative/02-address/rules.json +4 -0
  28. data/test/test_suite/aliases_negative/03-adult_age_in_user/aliases.json +31 -0
  29. data/test/test_suite/aliases_negative/03-adult_age_in_user/errors.json +8 -0
  30. data/test/test_suite/aliases_negative/03-adult_age_in_user/input.json +14 -0
  31. data/test/test_suite/aliases_negative/03-adult_age_in_user/rules.json +4 -0
  32. data/test/test_suite/aliases_positive/01-adult_age/aliases.json +12 -0
  33. data/test/test_suite/aliases_positive/01-adult_age/input.json +11 -0
  34. data/test/test_suite/aliases_positive/01-adult_age/output.json +10 -0
  35. data/test/test_suite/aliases_positive/01-adult_age/rules.json +10 -0
  36. data/test/test_suite/aliases_positive/02-address/aliases.json +20 -0
  37. data/test/test_suite/aliases_positive/02-address/input.json +13 -0
  38. data/test/test_suite/aliases_positive/02-address/output.json +12 -0
  39. data/test/test_suite/aliases_positive/02-address/rules.json +4 -0
  40. data/test/test_suite/aliases_positive/03-adult_age_in_user/aliases.json +31 -0
  41. data/test/test_suite/aliases_positive/03-adult_age_in_user/input.json +14 -0
  42. data/test/test_suite/aliases_positive/03-adult_age_in_user/output.json +12 -0
  43. data/test/test_suite/aliases_positive/03-adult_age_in_user/rules.json +4 -0
  44. data/test/test_suite/negative/01-required/errors.json +5 -0
  45. data/test/test_suite/negative/01-required/input.json +10 -0
  46. data/test/test_suite/negative/01-required/rules.json +10 -0
  47. data/test/test_suite/negative/02-not_empty/errors.json +3 -0
  48. data/test/test_suite/negative/02-not_empty/input.json +10 -0
  49. data/test/test_suite/negative/02-not_empty/rules.json +10 -0
  50. data/test/test_suite/negative/03-one_of/errors.json +10 -0
  51. data/test/test_suite/negative/03-one_of/input.json +11 -0
  52. data/test/test_suite/negative/03-one_of/rules.json +10 -0
  53. data/test/test_suite/negative/04-min_length/errors.json +10 -0
  54. data/test/test_suite/negative/04-min_length/input.json +12 -0
  55. data/test/test_suite/negative/04-min_length/rules.json +11 -0
  56. data/test/test_suite/negative/05-max_length/errors.json +10 -0
  57. data/test/test_suite/negative/05-max_length/input.json +12 -0
  58. data/test/test_suite/negative/05-max_length/rules.json +11 -0
  59. data/test/test_suite/negative/06-length_equal/errors.json +10 -0
  60. data/test/test_suite/negative/06-length_equal/input.json +12 -0
  61. data/test/test_suite/negative/06-length_equal/rules.json +11 -0
  62. data/test/test_suite/negative/07-length_between/errors.json +10 -0
  63. data/test/test_suite/negative/07-length_between/input.json +12 -0
  64. data/test/test_suite/negative/07-length_between/rules.json +11 -0
  65. data/test/test_suite/negative/08-like/errors.json +11 -0
  66. data/test/test_suite/negative/08-like/input.json +14 -0
  67. data/test/test_suite/negative/08-like/rules.json +12 -0
  68. data/test/test_suite/negative/09-integer/errors.json +10 -0
  69. data/test/test_suite/negative/09-integer/input.json +12 -0
  70. data/test/test_suite/negative/09-integer/rules.json +11 -0
  71. data/test/test_suite/negative/10-positive_integer/errors.json +10 -0
  72. data/test/test_suite/negative/10-positive_integer/input.json +12 -0
  73. data/test/test_suite/negative/10-positive_integer/rules.json +11 -0
  74. data/test/test_suite/negative/11-decimal/errors.json +10 -0
  75. data/test/test_suite/negative/11-decimal/input.json +12 -0
  76. data/test/test_suite/negative/11-decimal/rules.json +11 -0
  77. data/test/test_suite/negative/12-positive_decimal/errors.json +10 -0
  78. data/test/test_suite/negative/12-positive_decimal/input.json +12 -0
  79. data/test/test_suite/negative/12-positive_decimal/rules.json +11 -0
  80. data/test/test_suite/negative/13-max_number/errors.json +9 -0
  81. data/test/test_suite/negative/13-max_number/input.json +11 -0
  82. data/test/test_suite/negative/13-max_number/rules.json +10 -0
  83. data/test/test_suite/negative/14-min_number/errors.json +9 -0
  84. data/test/test_suite/negative/14-min_number/input.json +11 -0
  85. data/test/test_suite/negative/14-min_number/rules.json +10 -0
  86. data/test/test_suite/negative/15-number_beetween/errors.json +9 -0
  87. data/test/test_suite/negative/15-number_beetween/input.json +11 -0
  88. data/test/test_suite/negative/15-number_beetween/rules.json +10 -0
  89. data/test/test_suite/negative/16-email/errors.json +12 -0
  90. data/test/test_suite/negative/16-email/input.json +14 -0
  91. data/test/test_suite/negative/16-email/rules.json +13 -0
  92. data/test/test_suite/negative/17-equal_to_field/errors.json +10 -0
  93. data/test/test_suite/negative/17-equal_to_field/input.json +12 -0
  94. data/test/test_suite/negative/17-equal_to_field/rules.json +11 -0
  95. data/test/test_suite/negative/18-nested_object/errors.json +9 -0
  96. data/test/test_suite/negative/18-nested_object/input.json +9 -0
  97. data/test/test_suite/negative/18-nested_object/rules.json +9 -0
  98. data/test/test_suite/negative/19-list_of/errors.json +6 -0
  99. data/test/test_suite/negative/19-list_of/input.json +6 -0
  100. data/test/test_suite/negative/19-list_of/rules.json +14 -0
  101. data/test/test_suite/negative/20-list_of_objects/errors.json +14 -0
  102. data/test/test_suite/negative/20-list_of_objects/input.json +18 -0
  103. data/test/test_suite/negative/20-list_of_objects/rules.json +7 -0
  104. data/test/test_suite/negative/21-list_of_different_objects/errors.json +17 -0
  105. data/test/test_suite/negative/21-list_of_different_objects/input.json +26 -0
  106. data/test/test_suite/negative/21-list_of_different_objects/rules.json +17 -0
  107. data/test/test_suite/negative/22-not_empty_list/errors.json +7 -0
  108. data/test/test_suite/negative/22-not_empty_list/input.json +6 -0
  109. data/test/test_suite/negative/22-not_empty_list/rules.json +7 -0
  110. data/test/test_suite/negative/23-url/errors.json +10 -0
  111. data/test/test_suite/negative/23-url/input.json +12 -0
  112. data/test/test_suite/negative/23-url/rules.json +11 -0
  113. data/test/test_suite/negative/24-iso_date/errors.json +10 -0
  114. data/test/test_suite/negative/24-iso_date/input.json +12 -0
  115. data/test/test_suite/negative/24-iso_date/rules.json +11 -0
  116. data/test/test_suite/positive/01-required/input.json +7 -0
  117. data/test/test_suite/positive/01-required/output.json +6 -0
  118. data/test/test_suite/positive/01-required/rules.json +6 -0
  119. data/test/test_suite/positive/02-not_empty/input.json +6 -0
  120. data/test/test_suite/positive/02-not_empty/output.json +5 -0
  121. data/test/test_suite/positive/02-not_empty/rules.json +6 -0
  122. data/test/test_suite/positive/03-one_of/input.json +7 -0
  123. data/test/test_suite/positive/03-one_of/output.json +6 -0
  124. data/test/test_suite/positive/03-one_of/rules.json +6 -0
  125. data/test/test_suite/positive/04-min_length/input.json +7 -0
  126. data/test/test_suite/positive/04-min_length/output.json +6 -0
  127. data/test/test_suite/positive/04-min_length/rules.json +6 -0
  128. data/test/test_suite/positive/05-max_length/input.json +7 -0
  129. data/test/test_suite/positive/05-max_length/output.json +6 -0
  130. data/test/test_suite/positive/05-max_length/rules.json +6 -0
  131. data/test/test_suite/positive/06-length_equal/input.json +7 -0
  132. data/test/test_suite/positive/06-length_equal/output.json +6 -0
  133. data/test/test_suite/positive/06-length_equal/rules.json +6 -0
  134. data/test/test_suite/positive/07-length_between/input.json +7 -0
  135. data/test/test_suite/positive/07-length_between/output.json +6 -0
  136. data/test/test_suite/positive/07-length_between/rules.json +6 -0
  137. data/test/test_suite/positive/08-like/input.json +8 -0
  138. data/test/test_suite/positive/08-like/output.json +7 -0
  139. data/test/test_suite/positive/08-like/rules.json +7 -0
  140. data/test/test_suite/positive/09-integer/input.json +7 -0
  141. data/test/test_suite/positive/09-integer/output.json +6 -0
  142. data/test/test_suite/positive/09-integer/rules.json +6 -0
  143. data/test/test_suite/positive/10-positive_integer/input.json +7 -0
  144. data/test/test_suite/positive/10-positive_integer/output.json +6 -0
  145. data/test/test_suite/positive/10-positive_integer/rules.json +6 -0
  146. data/test/test_suite/positive/11-decimal/input.json +7 -0
  147. data/test/test_suite/positive/11-decimal/output.json +6 -0
  148. data/test/test_suite/positive/11-decimal/rules.json +6 -0
  149. data/test/test_suite/positive/12-positive_decimal/input.json +8 -0
  150. data/test/test_suite/positive/12-positive_decimal/output.json +7 -0
  151. data/test/test_suite/positive/12-positive_decimal/rules.json +7 -0
  152. data/test/test_suite/positive/13-max_number/input.json +7 -0
  153. data/test/test_suite/positive/13-max_number/output.json +6 -0
  154. data/test/test_suite/positive/13-max_number/rules.json +6 -0
  155. data/test/test_suite/positive/14-min_number/input.json +7 -0
  156. data/test/test_suite/positive/14-min_number/output.json +6 -0
  157. data/test/test_suite/positive/14-min_number/rules.json +6 -0
  158. data/test/test_suite/positive/15-number_between/input.json +7 -0
  159. data/test/test_suite/positive/15-number_between/output.json +6 -0
  160. data/test/test_suite/positive/15-number_between/rules.json +6 -0
  161. data/test/test_suite/positive/16-email/input.json +7 -0
  162. data/test/test_suite/positive/16-email/output.json +6 -0
  163. data/test/test_suite/positive/16-email/rules.json +6 -0
  164. data/test/test_suite/positive/17-equal_to_field/input.json +7 -0
  165. data/test/test_suite/positive/17-equal_to_field/output.json +6 -0
  166. data/test/test_suite/positive/17-equal_to_field/rules.json +6 -0
  167. data/test/test_suite/positive/18-nested_object/input.json +10 -0
  168. data/test/test_suite/positive/18-nested_object/output.json +8 -0
  169. data/test/test_suite/positive/18-nested_object/rules.json +8 -0
  170. data/test/test_suite/positive/19-list_of/input.json +6 -0
  171. data/test/test_suite/positive/19-list_of/output.json +6 -0
  172. data/test/test_suite/positive/19-list_of/rules.json +15 -0
  173. data/test/test_suite/positive/20-list_of_objects/input.json +16 -0
  174. data/test/test_suite/positive/20-list_of_objects/output.json +16 -0
  175. data/test/test_suite/positive/20-list_of_objects/rules.json +6 -0
  176. data/test/test_suite/positive/21-list_of_different_objects/input.json +21 -0
  177. data/test/test_suite/positive/21-list_of_different_objects/output.json +20 -0
  178. data/test/test_suite/positive/21-list_of_different_objects/rules.json +17 -0
  179. data/test/test_suite/positive/22-not_empty_list/input.json +6 -0
  180. data/test/test_suite/positive/22-not_empty_list/output.json +5 -0
  181. data/test/test_suite/positive/22-not_empty_list/rules.json +5 -0
  182. data/test/test_suite/positive/23-url/input.json +7 -0
  183. data/test/test_suite/positive/23-url/output.json +6 -0
  184. data/test/test_suite/positive/23-url/rules.json +6 -0
  185. data/test/test_suite/positive/24-iso_date/input.json +8 -0
  186. data/test/test_suite/positive/24-iso_date/output.json +7 -0
  187. data/test/test_suite/positive/24-iso_date/rules.json +7 -0
  188. data/test/test_suite/positive/30-trim/input.json +5 -0
  189. data/test/test_suite/positive/30-trim/output.json +5 -0
  190. data/test/test_suite/positive/30-trim/rules.json +5 -0
  191. data/test/test_suite/positive/31-to_lc/input.json +6 -0
  192. data/test/test_suite/positive/31-to_lc/output.json +6 -0
  193. data/test/test_suite/positive/31-to_lc/rules.json +6 -0
  194. data/test/test_suite/positive/32-to_uc/input.json +5 -0
  195. data/test/test_suite/positive/32-to_uc/output.json +5 -0
  196. data/test/test_suite/positive/32-to_uc/rules.json +5 -0
  197. data/test/test_suite/positive/33-remove/input.json +5 -0
  198. data/test/test_suite/positive/33-remove/output.json +5 -0
  199. data/test/test_suite/positive/33-remove/rules.json +7 -0
  200. data/test/test_suite/positive/34-leave_only/input.json +5 -0
  201. data/test/test_suite/positive/34-leave_only/output.json +5 -0
  202. data/test/test_suite/positive/34-leave_only/rules.json +7 -0
  203. metadata +476 -0
@@ -0,0 +1,21 @@
1
+ module Common
2
+ def self.required(args)
3
+ lambda do |value, unuse, unuse_|
4
+ return 'REQUIRED' if value.nil? or value.eql?('')
5
+ end
6
+ end
7
+
8
+ def self.not_empty(args)
9
+ lambda do |value, unuse, unuse_|
10
+ return 'CANNOT_BE_EMPTY' if !value.nil? and value.eql?('')
11
+ end
12
+ end
13
+
14
+ def self.not_empty_list(args)
15
+ lambda do |list, unuse, unuse_|
16
+ return 'CANNOT_BE_EMPTY' if list.eql?('') or list.nil?
17
+ return 'WRONG_FORMAT' unless list.kind_of? Array
18
+ return 'CANNOT_BE_EMPTY' if list.size.equal?(0)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,43 @@
1
+ module Filters
2
+ def self.trim(args)
3
+ lambda do |value, unuse, output|
4
+ return if value.nil? or value.eql?('') or not value.kind_of? String
5
+ output.push(value.strip! || value)
6
+ return nil
7
+ end
8
+ end
9
+
10
+ def self.to_lc(args)
11
+ lambda do |value, unuse, output|
12
+ return if value.nil? or value.eql?('') or not value.kind_of? String
13
+ output.push(value.downcase!)
14
+ return nil
15
+ end
16
+ end
17
+
18
+ def self.to_uc(args)
19
+ lambda do |value, unuse, output|
20
+ return if value.nil? or value.eql?('') or not value.kind_of? String
21
+ output.push(value.upcase!)
22
+ return nil
23
+ end
24
+ end
25
+
26
+ def self.remove(args)
27
+ chars = args.shift
28
+ lambda do |value, unuse, output|
29
+ return if value.nil? or value.eql?('') or not value.kind_of? String
30
+ output.push(value.gsub(/[#{Regexp.escape(chars)}]/, ''))
31
+ return nil
32
+ end
33
+ end
34
+
35
+ def self.leave_only(args)
36
+ chars = args.shift
37
+ lambda do |value, unuse, output|
38
+ return if value.nil? or value.eql?('') or not value.kind_of? String
39
+ output.push(value.gsub(/[^#{Regexp.escape(chars)}]/, ''))
40
+ return nil
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,126 @@
1
+ require 'LIVR'
2
+
3
+ module Helpers
4
+ def self.nested_object(args)
5
+ livr, rule_builders = args
6
+ validator = LIVR.new(livr).register_rules(rule_builders).prepare
7
+
8
+ lambda do |nested_obj, unuse, output|
9
+ return if nested_obj.nil? or nested_obj.eql?('')
10
+ return 'FORMAT_ERROR' unless nested_obj.kind_of? Hash
11
+
12
+ result = validator.validate(nested_obj)
13
+ if result
14
+ output.push(result)
15
+ return
16
+ else
17
+ return validator.get_errors
18
+ end
19
+ end
20
+ end
21
+
22
+ def self.list_of(args)
23
+ if args[0].kind_of? Array
24
+ rules, rule_builders = args
25
+ else
26
+ rule_builders = args.pop
27
+ rules = args
28
+ end
29
+ livr = {:field => rules}
30
+ validator = LIVR.new(livr).register_rules(rule_builders).prepare
31
+
32
+ lambda do |values, unuse, output|
33
+ return if values.nil? or values.eql?('')
34
+ return 'FORMAT_ERROR' unless values.kind_of? Array
35
+
36
+ results, errors = [], []
37
+ values.each do |val|
38
+ result = validator.validate({:field => val})
39
+ if result
40
+ results.push(result[:field])
41
+ errors.push(nil)
42
+ else
43
+ results.push(nil)
44
+ validatorErrors = validator.get_errors
45
+ errors.push(validatorErrors[:field])
46
+ end
47
+ end
48
+
49
+ if errors.any?
50
+ return errors
51
+ else
52
+ output.push(results)
53
+ return
54
+ end
55
+ end
56
+ end
57
+
58
+ def self.list_of_objects(args)
59
+ livr, rule_builders = args
60
+ validator = LIVR.new(livr).register_rules(rule_builders).prepare
61
+
62
+ lambda do |objects, unuse, output|
63
+ return if objects.nil? or objects.eql?('')
64
+ return 'FORMAT_ERROR' unless objects.kind_of? Array
65
+
66
+ results, errors = [], []
67
+ objects.each do |obj|
68
+ result = validator.validate(obj)
69
+
70
+ if result
71
+ results.push(result)
72
+ errors.push(nil)
73
+ else
74
+ results.push(nil)
75
+ errors.push(validator.get_errors)
76
+ end
77
+ end
78
+ if errors.any?
79
+ return errors
80
+ else
81
+ output.push(results)
82
+ return
83
+ end
84
+ end
85
+ end
86
+
87
+ def self.list_of_different_objects(args)
88
+ selector_field, livrs, rule_builders = args
89
+
90
+ validators = {}
91
+ livrs.each do |selector_value, livr|
92
+ validator = LIVR.new(livr).register_rules(rule_builders).prepare
93
+ validators[selector_value] = validator
94
+ end
95
+
96
+ lambda do |objects, unuse, output|
97
+ return if objects.nil? or objects.eql?('')
98
+ return 'FORMAT_ERROR' unless objects.kind_of? Array
99
+
100
+ results, errors = [], []
101
+ objects.each do |obj|
102
+ if not obj.kind_of? Hash or obj[selector_field].nil? or validators[obj[selector_field]].nil?
103
+ errors.push('FORMAT_ERROR')
104
+ next
105
+ end
106
+
107
+ validator = validators[obj[selector_field]]
108
+ result = validator.validate(obj)
109
+ if result
110
+ results.push(result)
111
+ errors.push(nil)
112
+ else
113
+ results.push(nil)
114
+ errors.push(validator.get_errors)
115
+ end
116
+ end
117
+
118
+ if errors.any?
119
+ return errors
120
+ else
121
+ output.push(results)
122
+ return
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,63 @@
1
+ require 'LIVR/Util'
2
+
3
+ module Numerics
4
+ def self.integers(args)
5
+ lambda do |value, unuse, unuse_|
6
+ return if value.nil? or value.eql?('')
7
+ return 'FORMAT_ERROR' unless Util.is_string_or_number?(value)
8
+ return 'NOT_INTEGER' unless value.to_s =~ /^\-?\d+$/
9
+ end
10
+ end
11
+
12
+ def self.positive_integer(args)
13
+ lambda do |value, unuse, unuse_|
14
+ return if value.nil? or value.eql?('')
15
+ return 'FORMAT_ERROR' unless Util.is_string_or_number?(value)
16
+ return 'NOT_POSITIVE_INTEGER' unless value.to_s =~ /^\d+$/ and value.to_i > 0
17
+ end
18
+ end
19
+
20
+ def self.decimal(args)
21
+ lambda do |value, unuse, unuse_|
22
+ return if value.nil? or value.eql?('')
23
+ return 'FORMAT_ERROR' unless Util.is_string_or_number?(value)
24
+ return 'NOT_DECIMAL' unless value.to_s =~ /^(?:\-?(?:[0-9]+\.[0-9]+)|(?:[0-9]+))$/
25
+ end
26
+ end
27
+
28
+ def self.positive_decimal(args)
29
+ lambda do |value, unuse, unuse_|
30
+ return if value.nil? or value.eql?('')
31
+ return 'FORMAT_ERROR' unless Util.is_string_or_number?(value)
32
+ return 'NOT_POSITIVE_DECIMAL' unless value.to_s =~ /^(?:(?:[0-9]*\.[0-9]+)|(?:[1-9][0-9]*))$/
33
+ end
34
+ end
35
+
36
+ def self.max_number(args)
37
+ max_number = args.shift.to_f
38
+ lambda do |value, unuse, unuse_|
39
+ return if value.nil? or value.eql?('')
40
+ return 'FORMAT_ERROR' unless Util.is_string_or_number?(value)
41
+ return 'TOO_HIGH' if value.to_f > max_number
42
+ end
43
+ end
44
+
45
+ def self.min_number(args)
46
+ min_number = args.shift.to_f
47
+ lambda do |value, unuse, unuse_|
48
+ return if value.nil? or value.eql?('')
49
+ return 'FORMAT_ERROR' unless Util.is_string_or_number?(value)
50
+ return 'TOO_LOW' if value.to_f < min_number
51
+ end
52
+ end
53
+
54
+ def self.number_between(args)
55
+ min_number, max_number = args
56
+ lambda do |value, unuse, unuse_|
57
+ return if value.nil? or value.eql?('')
58
+ return 'FORMAT_ERROR' unless Util.is_string_or_number?(value)
59
+ return 'TOO_LOW' if value.to_f < min_number
60
+ return 'TOO_HIGH' if value.to_f > max_number
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,55 @@
1
+ require 'uri'
2
+ require 'date'
3
+ require 'LIVR/Util'
4
+
5
+ module Special
6
+ def self.email(args)
7
+ email_re = %r(^([\w\-_+]+(?:\.[\w\-_+]+)*)@((?:[\w\-]+\.)*\w[\w\-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$)i
8
+
9
+ lambda do |value, unuse, unuse_|
10
+ return if value.nil? or value.eql?('')
11
+ return 'FORMAT_ERROR' unless value.kind_of? String
12
+
13
+ return 'WRONG_EMAIL' unless value =~ email_re
14
+ return 'WRONG_EMAIL' if value =~ %r(\@.*\@)
15
+ return 'WRONG_EMAIL' if value =~ %r(\@.*_)
16
+ end
17
+ end
18
+
19
+ def self.url(args)
20
+ url_re = %r(\A(http|https):\/\/([a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}|(25[0-5]|2[0-4]\d|[0-1]?\d?\d)
21
+ (\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}|localhost)(:[0-9]{1,5})?(\/.*)?\z)ix
22
+
23
+ lambda do |value, unuse, unuse_|
24
+ return if value.nil? or value.eql?('')
25
+ return 'FORMAT_ERROR' unless value.kind_of? String
26
+ return 'WRONG_URL' unless value =~ url_re
27
+ end
28
+ end
29
+
30
+ def self.iso_date(args)
31
+ date_re = %r(^(\d{4})-(\d{2})-(\d{2})$)
32
+
33
+ lambda do |value, unuse, unuse_|
34
+ return if value.nil? or value.eql?('')
35
+ return 'FORMAT_ERROR' unless value.kind_of? String
36
+ return 'WRONG_DATE' unless value =~ date_re
37
+ begin
38
+ DateTime.strptime(value, '%F')
39
+ return nil
40
+ rescue
41
+ return 'WRONG_DATE'
42
+ end
43
+ end
44
+ end
45
+
46
+ def self.equal_to_field(args)
47
+ field = args.shift
48
+
49
+ lambda do |value, params, unuse|
50
+ return if value.nil? or value.eql?('')
51
+ return 'FORMAT_ERROR' unless Util.is_string_or_number?(value)
52
+ return 'FIELDS_NOT_EQUAL' unless value == params[field]
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,71 @@
1
+ require 'LIVR/Util'
2
+
3
+ module Strings
4
+ def self.one_of(args)
5
+ if args[0].kind_of? Array
6
+ allowed_values = args.shift
7
+ else
8
+ args.pop # pop rule_builders
9
+ allowed_values = args
10
+ end
11
+
12
+ lambda do |value, unuse, unuse_|
13
+ return if value.nil? or value.eql?('')
14
+ return 'FORMAT_ERROR' unless value.kind_of? String
15
+ return 'NOT_ALLOWED_VALUE' unless allowed_values.include? value
16
+ end
17
+ end
18
+
19
+ def self.max_length(args)
20
+ max_length = args.shift.to_i
21
+
22
+ lambda do |value, unuse, unuse_|
23
+ return if value.nil? or value.eql?('')
24
+ return 'FORMAT_ERROR' unless value.kind_of? String
25
+ return 'TOO_LONG' if value.length > max_length
26
+ end
27
+ end
28
+
29
+ def self.min_length(args)
30
+ min_length = args.shift.to_i
31
+ lambda do |value, unuse, unuse_|
32
+ return if value.nil? or value.eql?('')
33
+ return 'FORMAT_ERROR' unless value.kind_of? String
34
+ return 'TOO_SHORT' if value.length < min_length
35
+ end
36
+ end
37
+
38
+ def self.length_equal(args)
39
+ length = args.shift.to_i
40
+ lambda do |value, unuse, unuse_|
41
+ return if value.nil? or value.eql?('')
42
+ return 'FORMAT_ERROR' unless value.kind_of? String
43
+ return 'TOO_SHORT' if value.length < length
44
+ return 'TOO_LONG' if value.length > length
45
+ end
46
+ end
47
+
48
+ def self.length_between(args)
49
+ min_length, max_length = args
50
+
51
+ lambda do |value, unuse, unuse_|
52
+ return if value.nil? or value.eql?('')
53
+ return 'FORMAT_ERROR' unless value.kind_of? String
54
+ return 'TOO_SHORT' if value.length < min_length
55
+ return 'TOO_LONG' if value.length > max_length
56
+ end
57
+ end
58
+
59
+ def self.like(args)
60
+ args.pop # pop rule_builders
61
+ re = args[0]
62
+ is_ignore_case = args.length == 2 && args[1] == 'i'
63
+ re = is_ignore_case ? %r(#{re})i : %r(#{re})
64
+
65
+ lambda do |value, unuse, unuse_|
66
+ return if value.nil? or value.eql?('')
67
+ return 'FORMAT_ERROR' unless Util.is_string_or_number?(value)
68
+ return 'WRONG_FORMAT' unless value =~ re
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,6 @@
1
+ module Util
2
+ def Util.is_string_or_number?(value)
3
+ return true if value.kind_of? Numeric or value.kind_of? String
4
+ return false
5
+ end
6
+ end
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "livr"
5
+
6
+ s.version = "0.0.2"
7
+
8
+ s.homepage = "https://github.com/maktwin/ruby-validator-livr"
9
+
10
+ s.summary = "Validator LIVR"
11
+
12
+ s.description = "Lightweight validator supporting Language Independent Rules Specification"
13
+
14
+ s.license = "Artistic_2_0"
15
+
16
+ s.authors = [
17
+ "Viktor Turskyi",
18
+ "Maksym Panchokha"
19
+ ]
20
+
21
+ s.email = ["m.panchoha@gmail.com"]
22
+
23
+ s.files = `git ls-files`.split("\n")
24
+ s.test_files = `git ls-files -- test/*`.split("\n")
25
+
26
+ s.add_development_dependency "rake"
27
+ s.add_development_dependency "minitest", "~> 5.4"
28
+ s.add_development_dependency "minitest-reporters", "~> 1.1"
29
+ end
@@ -0,0 +1,77 @@
1
+ require "test_helper"
2
+
3
+ class LIVRTest < Minitest::Test
4
+ def test_livr_positive
5
+ iterate_test_data(
6
+ 'test_suite/positive',
7
+ lambda do |data|
8
+ validator = LIVR.new(data['rules'])
9
+ output = validator.validate(data['input'])
10
+
11
+ assert(!validator.get_errors, 'Validator should contain no errors')
12
+ assert_equal(output, data['output'], 'Validator should return validated data')
13
+ end
14
+ )
15
+ end
16
+
17
+ def test_livr_negative
18
+ iterate_test_data(
19
+ 'test_suite/negative',
20
+ lambda do |data|
21
+ validator = LIVR.new(data['rules'])
22
+ output = validator.validate(data['input'])
23
+
24
+ assert(!output, 'Validator should return false')
25
+ assert_equal(data['errors'], validator.get_errors, 'Validator should contain valid errors')
26
+ end
27
+ )
28
+ end
29
+
30
+ def test_aliases_positive
31
+ iterate_test_data(
32
+ 'test_suite/aliases_positive',
33
+ lambda do |data|
34
+ validator = LIVR.new(data['rules'])
35
+ data['aliases'].each do |alias_hash|
36
+ validator.register_aliased_rule(alias_hash)
37
+ end
38
+ output = validator.validate(data['input'])
39
+
40
+ assert(!validator.get_errors, 'Validator should contain no errors')
41
+ assert_equal(output, data['output'], 'Validator should return validated data')
42
+ end
43
+ )
44
+ end
45
+
46
+ def test_aliases_negative
47
+ iterate_test_data(
48
+ 'test_suite/aliases_negative',
49
+ lambda do |data|
50
+ validator = LIVR.new(data['rules'])
51
+ data['aliases'].each do |alias_hash|
52
+ validator.register_aliased_rule(alias_hash)
53
+ end
54
+ output = validator.validate(data['input'])
55
+
56
+ assert(!output, 'Validator should return false')
57
+ assert_equal(validator.get_errors, data['errors'], 'Validator should contain valid errors')
58
+ end
59
+ )
60
+ end
61
+
62
+ def iterate_test_data(dir_basename, cb)
63
+ dir_fullname = "#{File.dirname(__FILE__)}/#{dir_basename}"
64
+ test_dirs = Dir["#{dir_fullname}/*"].sort!
65
+ test_dirs.each do |test_dir|
66
+ data = {}
67
+ Dir["#{test_dir}/*.json"].each do |test_data|
68
+ key_data = File.basename(test_data, ".json")
69
+ plain_data = File.read(test_data)
70
+ parsed_data = JSON.parse(plain_data)
71
+
72
+ data[key_data] = parsed_data
73
+ end
74
+ cb.call(data)
75
+ end
76
+ end
77
+ end