livr2 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (240) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +2 -0
  5. data/Gemfile.lock +45 -0
  6. data/Readme.md +114 -0
  7. data/lib/livr.rb +61 -0
  8. data/lib/livr/aliased_rule.rb +26 -0
  9. data/lib/livr/rule.rb +21 -0
  10. data/lib/livr/rules/common.rb +35 -0
  11. data/lib/livr/rules/meta.rb +200 -0
  12. data/lib/livr/rules/modifiers.rb +68 -0
  13. data/lib/livr/rules/numeric.rb +136 -0
  14. data/lib/livr/rules/special.rb +65 -0
  15. data/lib/livr/rules/string.rb +150 -0
  16. data/lib/livr/validator.rb +137 -0
  17. data/livr2.gemspec +19 -0
  18. data/spec/01-test_suite_spec.rb +34 -0
  19. data/spec/02-aliases_spec.rb +21 -0
  20. data/spec/03-auto_trim_spec.rb +56 -0
  21. data/spec/04-custom_filters_spec.rb +54 -0
  22. data/spec/05-rules_replacement_spec.rb +67 -0
  23. data/spec/spec_helper.rb +3 -0
  24. data/spec/test_suite/aliases_negative/01-adult_age/aliases.json +12 -0
  25. data/spec/test_suite/aliases_negative/01-adult_age/errors.json +6 -0
  26. data/spec/test_suite/aliases_negative/01-adult_age/input.json +11 -0
  27. data/spec/test_suite/aliases_negative/01-adult_age/rules.json +10 -0
  28. data/spec/test_suite/aliases_negative/02-address/aliases.json +20 -0
  29. data/spec/test_suite/aliases_negative/02-address/errors.json +8 -0
  30. data/spec/test_suite/aliases_negative/02-address/input.json +13 -0
  31. data/spec/test_suite/aliases_negative/02-address/rules.json +4 -0
  32. data/spec/test_suite/aliases_negative/03-adult_age_in_user/aliases.json +31 -0
  33. data/spec/test_suite/aliases_negative/03-adult_age_in_user/errors.json +8 -0
  34. data/spec/test_suite/aliases_negative/03-adult_age_in_user/input.json +14 -0
  35. data/spec/test_suite/aliases_negative/03-adult_age_in_user/rules.json +4 -0
  36. data/spec/test_suite/aliases_positive/01-adult_age/aliases.json +12 -0
  37. data/spec/test_suite/aliases_positive/01-adult_age/input.json +11 -0
  38. data/spec/test_suite/aliases_positive/01-adult_age/output.json +10 -0
  39. data/spec/test_suite/aliases_positive/01-adult_age/rules.json +10 -0
  40. data/spec/test_suite/aliases_positive/02-address/aliases.json +20 -0
  41. data/spec/test_suite/aliases_positive/02-address/input.json +13 -0
  42. data/spec/test_suite/aliases_positive/02-address/output.json +12 -0
  43. data/spec/test_suite/aliases_positive/02-address/rules.json +4 -0
  44. data/spec/test_suite/aliases_positive/03-adult_age_in_user/aliases.json +31 -0
  45. data/spec/test_suite/aliases_positive/03-adult_age_in_user/input.json +14 -0
  46. data/spec/test_suite/aliases_positive/03-adult_age_in_user/output.json +12 -0
  47. data/spec/test_suite/aliases_positive/03-adult_age_in_user/rules.json +4 -0
  48. data/spec/test_suite/negative/01-required/errors.json +5 -0
  49. data/spec/test_suite/negative/01-required/input.json +10 -0
  50. data/spec/test_suite/negative/01-required/rules.json +10 -0
  51. data/spec/test_suite/negative/02-not_empty/errors.json +3 -0
  52. data/spec/test_suite/negative/02-not_empty/input.json +10 -0
  53. data/spec/test_suite/negative/02-not_empty/rules.json +10 -0
  54. data/spec/test_suite/negative/03-one_of/errors.json +11 -0
  55. data/spec/test_suite/negative/03-one_of/input.json +12 -0
  56. data/spec/test_suite/negative/03-one_of/rules.json +11 -0
  57. data/spec/test_suite/negative/04-min_length/errors.json +10 -0
  58. data/spec/test_suite/negative/04-min_length/input.json +12 -0
  59. data/spec/test_suite/negative/04-min_length/rules.json +11 -0
  60. data/spec/test_suite/negative/05-max_length/errors.json +10 -0
  61. data/spec/test_suite/negative/05-max_length/input.json +12 -0
  62. data/spec/test_suite/negative/05-max_length/rules.json +11 -0
  63. data/spec/test_suite/negative/06-length_equal/errors.json +10 -0
  64. data/spec/test_suite/negative/06-length_equal/input.json +12 -0
  65. data/spec/test_suite/negative/06-length_equal/rules.json +11 -0
  66. data/spec/test_suite/negative/07-length_between/errors.json +10 -0
  67. data/spec/test_suite/negative/07-length_between/input.json +12 -0
  68. data/spec/test_suite/negative/07-length_between/rules.json +11 -0
  69. data/spec/test_suite/negative/08-like/errors.json +11 -0
  70. data/spec/test_suite/negative/08-like/input.json +14 -0
  71. data/spec/test_suite/negative/08-like/rules.json +12 -0
  72. data/spec/test_suite/negative/09-integer/errors.json +11 -0
  73. data/spec/test_suite/negative/09-integer/input.json +13 -0
  74. data/spec/test_suite/negative/09-integer/rules.json +12 -0
  75. data/spec/test_suite/negative/10-positive_integer/errors.json +11 -0
  76. data/spec/test_suite/negative/10-positive_integer/input.json +13 -0
  77. data/spec/test_suite/negative/10-positive_integer/rules.json +12 -0
  78. data/spec/test_suite/negative/11-decimal/errors.json +11 -0
  79. data/spec/test_suite/negative/11-decimal/input.json +13 -0
  80. data/spec/test_suite/negative/11-decimal/rules.json +12 -0
  81. data/spec/test_suite/negative/12-positive_decimal/errors.json +11 -0
  82. data/spec/test_suite/negative/12-positive_decimal/input.json +13 -0
  83. data/spec/test_suite/negative/12-positive_decimal/rules.json +12 -0
  84. data/spec/test_suite/negative/13-max_number/errors.json +10 -0
  85. data/spec/test_suite/negative/13-max_number/input.json +12 -0
  86. data/spec/test_suite/negative/13-max_number/rules.json +11 -0
  87. data/spec/test_suite/negative/14-min_number/errors.json +11 -0
  88. data/spec/test_suite/negative/14-min_number/input.json +13 -0
  89. data/spec/test_suite/negative/14-min_number/rules.json +12 -0
  90. data/spec/test_suite/negative/15-number_beetween/errors.json +12 -0
  91. data/spec/test_suite/negative/15-number_beetween/input.json +14 -0
  92. data/spec/test_suite/negative/15-number_beetween/rules.json +13 -0
  93. data/spec/test_suite/negative/16-email/errors.json +12 -0
  94. data/spec/test_suite/negative/16-email/input.json +14 -0
  95. data/spec/test_suite/negative/16-email/rules.json +13 -0
  96. data/spec/test_suite/negative/17-equal_to_field/errors.json +10 -0
  97. data/spec/test_suite/negative/17-equal_to_field/input.json +12 -0
  98. data/spec/test_suite/negative/17-equal_to_field/rules.json +11 -0
  99. data/spec/test_suite/negative/18-nested_object/errors.json +9 -0
  100. data/spec/test_suite/negative/18-nested_object/input.json +9 -0
  101. data/spec/test_suite/negative/18-nested_object/rules.json +9 -0
  102. data/spec/test_suite/negative/19-list_of/errors.json +6 -0
  103. data/spec/test_suite/negative/19-list_of/input.json +6 -0
  104. data/spec/test_suite/negative/19-list_of/rules.json +14 -0
  105. data/spec/test_suite/negative/20-list_of_objects/errors.json +14 -0
  106. data/spec/test_suite/negative/20-list_of_objects/input.json +18 -0
  107. data/spec/test_suite/negative/20-list_of_objects/rules.json +7 -0
  108. data/spec/test_suite/negative/21-list_of_different_objects/errors.json +17 -0
  109. data/spec/test_suite/negative/21-list_of_different_objects/input.json +26 -0
  110. data/spec/test_suite/negative/21-list_of_different_objects/rules.json +17 -0
  111. data/spec/test_suite/negative/22-not_empty_list/errors.json +7 -0
  112. data/spec/test_suite/negative/22-not_empty_list/input.json +6 -0
  113. data/spec/test_suite/negative/22-not_empty_list/rules.json +7 -0
  114. data/spec/test_suite/negative/23-url/errors.json +10 -0
  115. data/spec/test_suite/negative/23-url/input.json +12 -0
  116. data/spec/test_suite/negative/23-url/rules.json +11 -0
  117. data/spec/test_suite/negative/24-iso_date/errors.json +11 -0
  118. data/spec/test_suite/negative/24-iso_date/input.json +13 -0
  119. data/spec/test_suite/negative/24-iso_date/rules.json +12 -0
  120. data/spec/test_suite/negative/25-eq/errors.json +13 -0
  121. data/spec/test_suite/negative/25-eq/input.json +14 -0
  122. data/spec/test_suite/negative/25-eq/rules.json +13 -0
  123. data/spec/test_suite/negative/26-string/errors.json +6 -0
  124. data/spec/test_suite/negative/26-string/input.json +6 -0
  125. data/spec/test_suite/negative/26-string/rules.json +6 -0
  126. data/spec/test_suite/negative/27-any_object/errors.json +6 -0
  127. data/spec/test_suite/negative/27-any_object/input.json +6 -0
  128. data/spec/test_suite/negative/27-any_object/rules.json +6 -0
  129. data/spec/test_suite/negative/28-variable_object/errors.json +15 -0
  130. data/spec/test_suite/negative/28-variable_object/input.json +24 -0
  131. data/spec/test_suite/negative/28-variable_object/rules.json +77 -0
  132. data/spec/test_suite/negative/29-or/errors.json +14 -0
  133. data/spec/test_suite/negative/29-or/input.json +20 -0
  134. data/spec/test_suite/negative/29-or/rules.json +19 -0
  135. data/spec/test_suite/positive/01-required/input.json +7 -0
  136. data/spec/test_suite/positive/01-required/output.json +6 -0
  137. data/spec/test_suite/positive/01-required/rules.json +6 -0
  138. data/spec/test_suite/positive/02-not_empty/input.json +6 -0
  139. data/spec/test_suite/positive/02-not_empty/output.json +5 -0
  140. data/spec/test_suite/positive/02-not_empty/rules.json +6 -0
  141. data/spec/test_suite/positive/03-one_of/input.json +11 -0
  142. data/spec/test_suite/positive/03-one_of/output.json +10 -0
  143. data/spec/test_suite/positive/03-one_of/rules.json +10 -0
  144. data/spec/test_suite/positive/04-min_length/input.json +8 -0
  145. data/spec/test_suite/positive/04-min_length/output.json +7 -0
  146. data/spec/test_suite/positive/04-min_length/rules.json +8 -0
  147. data/spec/test_suite/positive/05-max_length/input.json +9 -0
  148. data/spec/test_suite/positive/05-max_length/output.json +8 -0
  149. data/spec/test_suite/positive/05-max_length/rules.json +9 -0
  150. data/spec/test_suite/positive/06-length_equal/input.json +8 -0
  151. data/spec/test_suite/positive/06-length_equal/output.json +7 -0
  152. data/spec/test_suite/positive/06-length_equal/rules.json +8 -0
  153. data/spec/test_suite/positive/07-length_between/input.json +9 -0
  154. data/spec/test_suite/positive/07-length_between/output.json +8 -0
  155. data/spec/test_suite/positive/07-length_between/rules.json +9 -0
  156. data/spec/test_suite/positive/08-like/input.json +8 -0
  157. data/spec/test_suite/positive/08-like/output.json +7 -0
  158. data/spec/test_suite/positive/08-like/rules.json +8 -0
  159. data/spec/test_suite/positive/09-integer/input.json +7 -0
  160. data/spec/test_suite/positive/09-integer/output.json +6 -0
  161. data/spec/test_suite/positive/09-integer/rules.json +7 -0
  162. data/spec/test_suite/positive/10-positive_integer/input.json +7 -0
  163. data/spec/test_suite/positive/10-positive_integer/output.json +6 -0
  164. data/spec/test_suite/positive/10-positive_integer/rules.json +6 -0
  165. data/spec/test_suite/positive/11-decimal/input.json +8 -0
  166. data/spec/test_suite/positive/11-decimal/output.json +7 -0
  167. data/spec/test_suite/positive/11-decimal/rules.json +7 -0
  168. data/spec/test_suite/positive/12-positive_decimal/input.json +8 -0
  169. data/spec/test_suite/positive/12-positive_decimal/output.json +7 -0
  170. data/spec/test_suite/positive/12-positive_decimal/rules.json +7 -0
  171. data/spec/test_suite/positive/13-max_number/input.json +7 -0
  172. data/spec/test_suite/positive/13-max_number/output.json +6 -0
  173. data/spec/test_suite/positive/13-max_number/rules.json +6 -0
  174. data/spec/test_suite/positive/14-min_number/input.json +7 -0
  175. data/spec/test_suite/positive/14-min_number/output.json +6 -0
  176. data/spec/test_suite/positive/14-min_number/rules.json +6 -0
  177. data/spec/test_suite/positive/15-number_between/input.json +8 -0
  178. data/spec/test_suite/positive/15-number_between/output.json +7 -0
  179. data/spec/test_suite/positive/15-number_between/rules.json +7 -0
  180. data/spec/test_suite/positive/16-email/input.json +7 -0
  181. data/spec/test_suite/positive/16-email/output.json +6 -0
  182. data/spec/test_suite/positive/16-email/rules.json +6 -0
  183. data/spec/test_suite/positive/17-equal_to_field/input.json +7 -0
  184. data/spec/test_suite/positive/17-equal_to_field/output.json +6 -0
  185. data/spec/test_suite/positive/17-equal_to_field/rules.json +6 -0
  186. data/spec/test_suite/positive/18-nested_object/input.json +15 -0
  187. data/spec/test_suite/positive/18-nested_object/output.json +12 -0
  188. data/spec/test_suite/positive/18-nested_object/rules.json +13 -0
  189. data/spec/test_suite/positive/19-list_of/input.json +7 -0
  190. data/spec/test_suite/positive/19-list_of/output.json +7 -0
  191. data/spec/test_suite/positive/19-list_of/rules.json +15 -0
  192. data/spec/test_suite/positive/20-list_of_objects/input.json +17 -0
  193. data/spec/test_suite/positive/20-list_of_objects/output.json +17 -0
  194. data/spec/test_suite/positive/20-list_of_objects/rules.json +10 -0
  195. data/spec/test_suite/positive/21-list_of_different_objects/input.json +22 -0
  196. data/spec/test_suite/positive/21-list_of_different_objects/output.json +21 -0
  197. data/spec/test_suite/positive/21-list_of_different_objects/rules.json +27 -0
  198. data/spec/test_suite/positive/22-not_empty_list/input.json +6 -0
  199. data/spec/test_suite/positive/22-not_empty_list/output.json +5 -0
  200. data/spec/test_suite/positive/22-not_empty_list/rules.json +5 -0
  201. data/spec/test_suite/positive/23-url/input.json +7 -0
  202. data/spec/test_suite/positive/23-url/output.json +6 -0
  203. data/spec/test_suite/positive/23-url/rules.json +6 -0
  204. data/spec/test_suite/positive/24-iso_date/input.json +9 -0
  205. data/spec/test_suite/positive/24-iso_date/output.json +8 -0
  206. data/spec/test_suite/positive/24-iso_date/rules.json +8 -0
  207. data/spec/test_suite/positive/25-eq/input.json +10 -0
  208. data/spec/test_suite/positive/25-eq/output.json +9 -0
  209. data/spec/test_suite/positive/25-eq/rules.json +9 -0
  210. data/spec/test_suite/positive/26-string/input.json +8 -0
  211. data/spec/test_suite/positive/26-string/output.json +7 -0
  212. data/spec/test_suite/positive/26-string/rules.json +7 -0
  213. data/spec/test_suite/positive/27-any_object/input.json +6 -0
  214. data/spec/test_suite/positive/27-any_object/output.json +6 -0
  215. data/spec/test_suite/positive/27-any_object/rules.json +7 -0
  216. data/spec/test_suite/positive/28-variable_object/input.json +19 -0
  217. data/spec/test_suite/positive/28-variable_object/output.json +18 -0
  218. data/spec/test_suite/positive/28-variable_object/rules.json +47 -0
  219. data/spec/test_suite/positive/29-or/input.json +25 -0
  220. data/spec/test_suite/positive/29-or/output.json +24 -0
  221. data/spec/test_suite/positive/29-or/rules.json +24 -0
  222. data/spec/test_suite/positive/30-trim/input.json +7 -0
  223. data/spec/test_suite/positive/30-trim/output.json +7 -0
  224. data/spec/test_suite/positive/30-trim/rules.json +7 -0
  225. data/spec/test_suite/positive/31-to_lc/input.json +8 -0
  226. data/spec/test_suite/positive/31-to_lc/output.json +8 -0
  227. data/spec/test_suite/positive/31-to_lc/rules.json +8 -0
  228. data/spec/test_suite/positive/32-to_uc/input.json +7 -0
  229. data/spec/test_suite/positive/32-to_uc/output.json +7 -0
  230. data/spec/test_suite/positive/32-to_uc/rules.json +7 -0
  231. data/spec/test_suite/positive/33-remove/input.json +5 -0
  232. data/spec/test_suite/positive/33-remove/output.json +5 -0
  233. data/spec/test_suite/positive/33-remove/rules.json +7 -0
  234. data/spec/test_suite/positive/34-leave_only/input.json +5 -0
  235. data/spec/test_suite/positive/34-leave_only/output.json +5 -0
  236. data/spec/test_suite/positive/34-leave_only/rules.json +7 -0
  237. data/spec/test_suite/positive/35-default/input.json +10 -0
  238. data/spec/test_suite/positive/35-default/output.json +12 -0
  239. data/spec/test_suite/positive/35-default/rules.json +12 -0
  240. metadata +531 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 81c9134b5dc59c32088f0b285b159697bfbbeb1a
4
+ data.tar.gz: 59b4324bcefda407cbe41a677cc553abe72bafd6
5
+ SHA512:
6
+ metadata.gz: df65daa6d49b6444826e8e510f912cf7f84519b0fc28699e534b673279ae3f6099656a956ebace58d947bdfa416f5e8b1486f888e92c1cec5781c8a7409b1161
7
+ data.tar.gz: 7a150d4c4ce0108f60a5285aff998fbb64598c020c354c3cbf62c4fba01219ab3da82e8936466e48d41bdd1b3a955d78afa29f3e6d78c7fb82f62dc82b7e9641
@@ -0,0 +1 @@
1
+ .ruby-version
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color spec
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "https://rubygems.org"
2
+ gemspec
@@ -0,0 +1,45 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ livr2 (2.0.0)
5
+ activesupport (~> 5)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activesupport (5.1.4)
11
+ concurrent-ruby (~> 1.0, >= 1.0.2)
12
+ i18n (~> 0.7)
13
+ minitest (~> 5.1)
14
+ tzinfo (~> 1.1)
15
+ concurrent-ruby (1.0.5)
16
+ diff-lcs (1.3)
17
+ i18n (0.9.1)
18
+ concurrent-ruby (~> 1.0)
19
+ minitest (5.10.3)
20
+ rspec (3.7.0)
21
+ rspec-core (~> 3.7.0)
22
+ rspec-expectations (~> 3.7.0)
23
+ rspec-mocks (~> 3.7.0)
24
+ rspec-core (3.7.0)
25
+ rspec-support (~> 3.7.0)
26
+ rspec-expectations (3.7.0)
27
+ diff-lcs (>= 1.2.0, < 2.0)
28
+ rspec-support (~> 3.7.0)
29
+ rspec-mocks (3.7.0)
30
+ diff-lcs (>= 1.2.0, < 2.0)
31
+ rspec-support (~> 3.7.0)
32
+ rspec-support (3.7.0)
33
+ thread_safe (0.3.6)
34
+ tzinfo (1.2.4)
35
+ thread_safe (~> 0.1)
36
+
37
+ PLATFORMS
38
+ ruby
39
+
40
+ DEPENDENCIES
41
+ livr2!
42
+ rspec (= 3.7)
43
+
44
+ BUNDLED WITH
45
+ 1.16.0.pre.3
@@ -0,0 +1,114 @@
1
+
2
+ # LIVR Validator
3
+ LIVR.Validator - Lightweight validator supporting Language Independent Validation Rules Specification (LIVR)
4
+
5
+ # SYNOPSIS
6
+ Common usage:
7
+
8
+ ```ruby
9
+ gem 'livr2'
10
+ require 'livr'
11
+
12
+ validator = LIVR::Validator.new({
13
+ 'name' => 'required',
14
+ 'email' => [ 'required', 'email' ],
15
+ 'gender' => { 'one_of' => ['male', 'female'] },
16
+ 'phone' => { 'max_length' => 10 },
17
+ 'password' => [ 'required', {min_length : 10} ],
18
+ 'password2' => { 'equal_to_field' => 'password' }
19
+ });
20
+
21
+ valid_data = validator.validate(user_data)
22
+
23
+ if (valid_data) {
24
+ save_user(validData)
25
+ } else {
26
+ handle_errors(validator.get_errors)
27
+ }
28
+ ```
29
+
30
+
31
+ You can use modifiers separately or can combine them with validation:
32
+
33
+ ```ruby
34
+ var validator = LIVR::Validator.new({
35
+ email: [ 'required', 'trim', 'email', 'to_lc' ]
36
+ });
37
+ ```
38
+
39
+
40
+ Feel free to register your own rules:
41
+
42
+ You can use aliases(prefferable, syntax covered by the specification) for a lot of cases:
43
+
44
+ ```ruby
45
+ var validator = LIVR::Validator.new({
46
+ password: ['required', 'strong_password']
47
+ });
48
+
49
+ validator.register_aliased_rule({
50
+ name: 'strong_password',
51
+ rules: {min_length: 6},
52
+ error: 'WEAK_PASSWORD'
53
+ });
54
+ ```
55
+
56
+ Or you can write more sophisticated rules directly:
57
+
58
+ ```ruby
59
+ validator = LIVR::Validator.new({
60
+ password: ['required', 'strong_password']
61
+ })
62
+
63
+ class StrongPassword
64
+ def call(value, *other_args)
65
+ # We already have "required" rule to check that the value is present
66
+ return if value == nil || value == ""
67
+ if value.length < 6
68
+ return 'WEAK_PASSWORD'
69
+ end
70
+ end
71
+ end
72
+ ```
73
+
74
+ # DESCRIPTION
75
+ This ruby gem is an implementation of LIVR Specification.
76
+ See ['LIVR Specification'](http://livr-spec.org) for detailed documentation and list of supported rules.
77
+
78
+ Features:
79
+
80
+ * Rules are declarative and language independent
81
+ * Any number of rules for each field
82
+ * Return together errors for all fields
83
+ * Excludes all fields that do not have validation rules described
84
+ * Has possibility to validatate complex hierarchical structures
85
+ * Easy to describe and undersand rules
86
+ * Returns understandable error codes(not error messages)
87
+ * Easy to add own rules
88
+ * Rules are be able to change results output ("trim", "nested\_object", for example)
89
+ * Multipurpose (user input validation, configs validation, contracts programming etc)
90
+
91
+ # INSTALL
92
+
93
+ #### as a gem
94
+
95
+ ```bash
96
+ gem install livr2
97
+ ```
98
+
99
+ #### in rails
100
+
101
+ Add to Gemfile
102
+
103
+ ```ruby
104
+ gem "livr2"
105
+ ```
106
+
107
+
108
+ # AUTHORS
109
+
110
+ ## Ruby implementation
111
+ Vitaliy Yanchuk (@fuksito)
112
+
113
+ ## Idea and specification
114
+ Viktor Turskyi (@koorchik)
@@ -0,0 +1,61 @@
1
+ require 'pry'
2
+ require 'json'
3
+ require 'date'
4
+ require 'active_support/all'
5
+
6
+ require_relative "livr/validator.rb"
7
+ require_relative "livr/rule.rb"
8
+ require_relative "livr/aliased_rule.rb"
9
+ require_relative "livr/rules/common.rb"
10
+ require_relative "livr/rules/string.rb"
11
+ require_relative "livr/rules/numeric.rb"
12
+ require_relative "livr/rules/special.rb"
13
+ require_relative "livr/rules/modifiers.rb"
14
+ require_relative "livr/rules/meta.rb"
15
+
16
+ module LIVR
17
+ DEFAULT_RULES = {
18
+ required: Rules::Common::Required,
19
+ not_empty: Rules::Common::NotEmpty,
20
+ not_empty_list: Rules::Common::NotEmptyList,
21
+ any_object: Rules::Common::AnyObject,
22
+
23
+ string: Rules::String::String,
24
+ eq: Rules::String::Eq,
25
+ one_of: Rules::String::OneOf,
26
+ max_length: Rules::String::MaxLength,
27
+ min_length: Rules::String::MinLength,
28
+ length_equal: Rules::String::LengthEqual,
29
+ length_between: Rules::String::LengthBetween,
30
+ like: Rules::String::Like,
31
+
32
+ integer: Rules::Numeric::Integer,
33
+ positive_integer: Rules::Numeric::PositiveInteger,
34
+ decimal: Rules::Numeric::Decimal,
35
+ positive_decimal: Rules::Numeric::PositiveDecimal,
36
+ max_number: Rules::Numeric::MaxNumber,
37
+ min_number: Rules::Numeric::MinNumber,
38
+ number_between: Rules::Numeric::NumberBetween,
39
+
40
+ email: Rules::Special::Email,
41
+ equal_to_field: Rules::Special::EqualToField,
42
+ url: Rules::Special::Url,
43
+ iso_date: Rules::Special::IsoDate,
44
+
45
+ default: Rules::Modifiers::Default,
46
+ trim: Rules::Modifiers::Trim,
47
+ to_lc: Rules::Modifiers::ToLc,
48
+ to_uc: Rules::Modifiers::ToUc,
49
+ remove: Rules::Modifiers::Remove,
50
+ leave_only: Rules::Modifiers::LeaveOnly,
51
+
52
+ nested_object: Rules::Meta::NestedObject,
53
+ variable_object: Rules::Meta::VariableObject,
54
+ list_of: Rules::Meta::ListOf,
55
+ list_of_objects: Rules::Meta::ListOfObjects,
56
+ list_of_different_objects: Rules::Meta::ListOfDifferentObjects,
57
+ or: Rules::Meta::Or,
58
+ }.with_indifferent_access
59
+
60
+ Validator.register_default_rules(DEFAULT_RULES)
61
+ end
@@ -0,0 +1,26 @@
1
+ module LIVR
2
+ class AliasedRule
3
+
4
+ def initialize(_alias)
5
+ raise "Alias name required" unless _alias["name"]
6
+ raise "Alias rules required" unless _alias["rules"].present?
7
+
8
+ @alias = _alias
9
+ @validator = Validator.new(value: Array.wrap(@alias["rules"]))
10
+ end
11
+
12
+ def new(*args)
13
+ self
14
+ end
15
+
16
+ def call(value, user_data, field_results)
17
+ result = @validator.validate({ value: value })
18
+ if result
19
+ field_results << result[:value]
20
+ return
21
+ else
22
+ return @alias.fetch("error", @validator.get_errors)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,21 @@
1
+ module LIVR
2
+ class Rule
3
+
4
+ def initialize(*)
5
+ end
6
+
7
+ def call(value, user_data, field_results)
8
+ raise NotImplementedError
9
+ end
10
+
11
+ private
12
+
13
+ def is_primitive(value)
14
+ [Numeric, String, TrueClass, FalseClass].any?{|klass| value.is_a?(klass) }
15
+ end
16
+
17
+ def is_no_value(value)
18
+ value == nil || value == ""
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,35 @@
1
+ module LIVR
2
+ module Rules
3
+ module Common
4
+
5
+ class Required < Rule
6
+ def call(value, user_data, field_results)
7
+ return if value.in?([[], {}])
8
+ "REQUIRED" if value.blank?
9
+ end
10
+ end
11
+
12
+ class NotEmpty < Rule
13
+ def call(value, user_data, field_results)
14
+ "CANNOT_BE_EMPTY" if value == ""
15
+ end
16
+ end
17
+
18
+ class NotEmptyList < Rule
19
+ def call(list, user_data, field_results)
20
+ return "CANNOT_BE_EMPTY" if is_no_value(list)
21
+ return "CANNOT_BE_EMPTY" if list.is_a?(Array) && list.blank?
22
+ return "FORMAT_ERROR" unless list.is_a?(Array)
23
+ end
24
+ end
25
+
26
+ class AnyObject < Rule
27
+ def call(value, user_data, field_results)
28
+ return if is_no_value(value)
29
+ return "FORMAT_ERROR" unless value.is_a?(Hash)
30
+ end
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,200 @@
1
+ module LIVR
2
+ module Rules
3
+ module Meta
4
+
5
+ class NestedObject < Rule
6
+ def initialize(livr)
7
+ @validator = Validator.new(livr).prepare
8
+ end
9
+
10
+ def call(nested_object, user_data, field_results)
11
+ return if is_no_value(nested_object)
12
+ return 'FORMAT_ERROR' unless nested_object.is_a?(Hash)
13
+
14
+ result = @validator.validate(nested_object)
15
+
16
+ if result
17
+ field_results << result
18
+ return
19
+ else
20
+ return @validator.get_errors
21
+ end
22
+ end
23
+ end
24
+
25
+ class VariableObject < Rule
26
+ def initialize(selector_field, livrs)
27
+ @selector_field = selector_field
28
+ @validators = {}
29
+ livrs.each do |selector_value, livr|
30
+ @validators[selector_value] = Validator.new(livr).prepare
31
+ end
32
+ end
33
+
34
+ def call(object, user_data, field_results)
35
+ return if is_no_value(object)
36
+ if ( !object.is_a?(Hash) || !object[@selector_field] || !@validators[ object[@selector_field] ] )
37
+ return 'FORMAT_ERROR'
38
+ end
39
+
40
+ validator = @validators.fetch(object.fetch(@selector_field))
41
+ result = validator.validate(object)
42
+
43
+ if result
44
+ field_results << result
45
+ return
46
+ else
47
+ return validator.get_errors
48
+ end
49
+ end
50
+ end
51
+
52
+ class ListOf < Rule
53
+ def initialize(*rules)
54
+ livr = { field: rules.flatten }
55
+ @validator = Validator.new(livr).prepare
56
+ end
57
+
58
+ def call(values, user_data, field_results)
59
+ return if is_no_value(values)
60
+ return 'FORMAT_ERROR' unless values.is_a?(Array)
61
+
62
+ results = []
63
+ errors = []
64
+ has_errors = false
65
+
66
+ values.each do |value|
67
+ result = @validator.validate(field: value)
68
+
69
+ if result
70
+ results << result[:field]
71
+ errors << nil
72
+ else
73
+ has_errors = true
74
+ errors << @validator.get_errors[:field]
75
+ results << nil
76
+ end
77
+ end
78
+
79
+ if has_errors
80
+ return errors
81
+ else
82
+ field_results << results
83
+ return
84
+ end
85
+ end
86
+ end
87
+
88
+ class ListOfObjects < Rule
89
+ def initialize(livr)
90
+ @validator = Validator.new(livr).prepare
91
+ end
92
+
93
+ def call(objects, user_data, field_results)
94
+ return if is_no_value(objects)
95
+ return 'FORMAT_ERROR' unless objects.is_a?(Array)
96
+
97
+ results = []
98
+ errors = []
99
+ has_errors = false
100
+
101
+ objects.each do |object|
102
+ result = @validator.validate(object)
103
+
104
+ if result
105
+ results << result
106
+ errors << nil
107
+ else
108
+ has_errors = true
109
+ errors << @validator.get_errors
110
+ results << nil
111
+ end
112
+ end
113
+
114
+ if has_errors
115
+ return errors
116
+ else
117
+ field_results << results
118
+ return
119
+ end
120
+
121
+ end
122
+ end
123
+
124
+ class ListOfDifferentObjects < Rule
125
+ def initialize(selector_field, livrs)
126
+ @selector_field = selector_field
127
+ @validators = {}
128
+ livrs.each do |selector_value, livr|
129
+ @validators[selector_value] = Validator.new(livr).prepare
130
+ end
131
+ end
132
+
133
+ def call(objects, user_data, field_results)
134
+ return if is_no_value(objects)
135
+ return 'FORMAT_ERROR' unless objects.is_a?(Array)
136
+
137
+ results = []
138
+ errors = []
139
+ has_errors = false
140
+
141
+ objects.each do |object|
142
+ if !object.is_a?(Hash) || !object[@selector_field] || !@validators[ object[@selector_field] ]
143
+ errors << 'FORMAT_ERROR'
144
+ next
145
+ end
146
+
147
+ validator = @validators[ object[@selector_field] ]
148
+ result = validator.validate(object)
149
+
150
+ if result
151
+ results << result
152
+ errors << nil
153
+ else
154
+ has_errors = true
155
+ errors << validator.get_errors
156
+ results << nil
157
+ end
158
+ end
159
+
160
+ if has_errors
161
+ return errors
162
+ else
163
+ field_results << results
164
+ return
165
+ end
166
+ end
167
+ end
168
+
169
+
170
+ class Or < Rule
171
+ def initialize(*rule_sets)
172
+ @rule_sets = rule_sets
173
+ @validators = @rule_sets.map do |rules|
174
+ livr = { field: rules }
175
+ Validator.new(livr).prepare
176
+ end
177
+ end
178
+
179
+ def call(value, user_data, field_results)
180
+ return if is_no_value(value)
181
+
182
+ last_error = nil
183
+ @validators.each do |validator|
184
+ result = validator.validate(field: value)
185
+ if result
186
+ field_results << result[:field]
187
+ return nil
188
+ else
189
+ last_error = validator.get_errors[:field]
190
+ end
191
+ end
192
+
193
+ last_error ? last_error : nil
194
+ end
195
+ end
196
+
197
+ end
198
+ end
199
+ end
200
+