schemacop 2.4.7 → 3.0.0.rc0

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 (172) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.rubocop.yml +25 -1
  4. data/.travis.yml +2 -1
  5. data/CHANGELOG.md +8 -0
  6. data/README.md +41 -708
  7. data/README_V2.md +775 -0
  8. data/README_V3.md +683 -0
  9. data/Rakefile +8 -12
  10. data/VERSION +1 -1
  11. data/lib/schemacop.rb +35 -37
  12. data/lib/schemacop/base_schema.rb +37 -0
  13. data/lib/schemacop/railtie.rb +10 -0
  14. data/lib/schemacop/schema.rb +1 -60
  15. data/lib/schemacop/schema2.rb +22 -0
  16. data/lib/schemacop/schema3.rb +21 -0
  17. data/lib/schemacop/scoped_env.rb +25 -13
  18. data/lib/schemacop/v2.rb +26 -0
  19. data/lib/schemacop/{caster.rb → v2/caster.rb} +16 -2
  20. data/lib/schemacop/{collector.rb → v2/collector.rb} +5 -2
  21. data/lib/schemacop/{dupper.rb → v2/dupper.rb} +1 -1
  22. data/lib/schemacop/{field_node.rb → v2/field_node.rb} +4 -3
  23. data/lib/schemacop/v2/node.rb +142 -0
  24. data/lib/schemacop/{node_resolver.rb → v2/node_resolver.rb} +1 -1
  25. data/lib/schemacop/{node_supporting_field.rb → v2/node_supporting_field.rb} +8 -10
  26. data/lib/schemacop/{node_supporting_type.rb → v2/node_supporting_type.rb} +6 -3
  27. data/lib/schemacop/{node_with_block.rb → v2/node_with_block.rb} +3 -2
  28. data/lib/schemacop/v2/root_node.rb +6 -0
  29. data/lib/schemacop/v2/validator/array_validator.rb +32 -0
  30. data/lib/schemacop/{validator → v2/validator}/boolean_validator.rb +1 -1
  31. data/lib/schemacop/v2/validator/float_validator.rb +7 -0
  32. data/lib/schemacop/v2/validator/hash_validator.rb +37 -0
  33. data/lib/schemacop/v2/validator/integer_validator.rb +7 -0
  34. data/lib/schemacop/{validator → v2/validator}/nil_validator.rb +1 -1
  35. data/lib/schemacop/v2/validator/number_validator.rb +21 -0
  36. data/lib/schemacop/v2/validator/object_validator.rb +29 -0
  37. data/lib/schemacop/v2/validator/string_validator.rb +39 -0
  38. data/lib/schemacop/{validator → v2/validator}/symbol_validator.rb +1 -1
  39. data/lib/schemacop/v3.rb +45 -0
  40. data/lib/schemacop/v3/all_of_node.rb +27 -0
  41. data/lib/schemacop/v3/any_of_node.rb +28 -0
  42. data/lib/schemacop/v3/array_node.rb +219 -0
  43. data/lib/schemacop/v3/boolean_node.rb +16 -0
  44. data/lib/schemacop/v3/combination_node.rb +45 -0
  45. data/lib/schemacop/v3/context.rb +17 -0
  46. data/lib/schemacop/v3/dsl_scope.rb +46 -0
  47. data/lib/schemacop/v3/global_context.rb +114 -0
  48. data/lib/schemacop/v3/hash_node.rb +217 -0
  49. data/lib/schemacop/v3/integer_node.rb +13 -0
  50. data/lib/schemacop/v3/is_not_node.rb +32 -0
  51. data/lib/schemacop/v3/node.rb +214 -0
  52. data/lib/schemacop/v3/node_registry.rb +49 -0
  53. data/lib/schemacop/v3/number_node.rb +18 -0
  54. data/lib/schemacop/v3/numeric_node.rb +76 -0
  55. data/lib/schemacop/v3/object_node.rb +40 -0
  56. data/lib/schemacop/v3/one_of_node.rb +28 -0
  57. data/lib/schemacop/v3/reference_node.rb +49 -0
  58. data/lib/schemacop/v3/result.rb +58 -0
  59. data/lib/schemacop/v3/string_node.rb +124 -0
  60. data/lib/schemacop/v3/symbol_node.rb +13 -0
  61. data/schemacop.gemspec +24 -27
  62. data/test/lib/test_helper.rb +152 -0
  63. data/test/schemas/nested/group.rb +6 -0
  64. data/test/schemas/user.rb +7 -0
  65. data/test/unit/schemacop/v2/casting_test.rb +120 -0
  66. data/test/unit/schemacop/v2/collector_test.rb +47 -0
  67. data/test/unit/schemacop/v2/custom_check_test.rb +95 -0
  68. data/test/unit/schemacop/v2/custom_if_test.rb +97 -0
  69. data/test/unit/schemacop/v2/defaults_test.rb +95 -0
  70. data/test/unit/schemacop/v2/empty_test.rb +16 -0
  71. data/test/unit/schemacop/v2/nil_dis_allow_test.rb +43 -0
  72. data/test/unit/schemacop/v2/node_resolver_test.rb +28 -0
  73. data/test/unit/schemacop/v2/short_forms_test.rb +351 -0
  74. data/test/unit/schemacop/v2/types_test.rb +88 -0
  75. data/test/unit/schemacop/v2/validator_array_test.rb +99 -0
  76. data/test/unit/schemacop/v2/validator_boolean_test.rb +17 -0
  77. data/test/unit/schemacop/v2/validator_float_test.rb +59 -0
  78. data/test/unit/schemacop/v2/validator_hash_test.rb +95 -0
  79. data/test/unit/schemacop/v2/validator_integer_test.rb +48 -0
  80. data/test/unit/schemacop/v2/validator_nil_test.rb +15 -0
  81. data/test/unit/schemacop/v2/validator_number_test.rb +62 -0
  82. data/test/unit/schemacop/v2/validator_object_test.rb +141 -0
  83. data/test/unit/schemacop/v2/validator_string_test.rb +78 -0
  84. data/test/unit/schemacop/v2/validator_symbol_test.rb +18 -0
  85. data/test/unit/schemacop/v3/all_of_node_test.rb +199 -0
  86. data/test/unit/schemacop/v3/any_of_node_test.rb +218 -0
  87. data/test/unit/schemacop/v3/array_node_test.rb +805 -0
  88. data/test/unit/schemacop/v3/boolean_node_test.rb +126 -0
  89. data/test/unit/schemacop/v3/global_context_test.rb +164 -0
  90. data/test/unit/schemacop/v3/hash_node_test.rb +775 -0
  91. data/test/unit/schemacop/v3/integer_node_test.rb +323 -0
  92. data/test/unit/schemacop/v3/is_not_node_test.rb +173 -0
  93. data/test/unit/schemacop/v3/node_test.rb +148 -0
  94. data/test/unit/schemacop/v3/number_node_test.rb +292 -0
  95. data/test/unit/schemacop/v3/object_node_test.rb +170 -0
  96. data/test/unit/schemacop/v3/one_of_node_test.rb +187 -0
  97. data/test/unit/schemacop/v3/reference_node_test.rb +351 -0
  98. data/test/unit/schemacop/v3/string_node_test.rb +334 -0
  99. data/test/unit/schemacop/v3/symbol_node_test.rb +75 -0
  100. metadata +152 -145
  101. data/doc/Schemacop.html +0 -146
  102. data/doc/Schemacop/ArrayValidator.html +0 -329
  103. data/doc/Schemacop/BooleanValidator.html +0 -145
  104. data/doc/Schemacop/Caster.html +0 -379
  105. data/doc/Schemacop/Collector.html +0 -787
  106. data/doc/Schemacop/Dupper.html +0 -214
  107. data/doc/Schemacop/Exceptions.html +0 -115
  108. data/doc/Schemacop/Exceptions/InvalidSchemaError.html +0 -124
  109. data/doc/Schemacop/Exceptions/ValidationError.html +0 -124
  110. data/doc/Schemacop/FieldNode.html +0 -421
  111. data/doc/Schemacop/FloatValidator.html +0 -158
  112. data/doc/Schemacop/HashValidator.html +0 -293
  113. data/doc/Schemacop/IntegerValidator.html +0 -158
  114. data/doc/Schemacop/NilValidator.html +0 -145
  115. data/doc/Schemacop/Node.html +0 -1438
  116. data/doc/Schemacop/NodeResolver.html +0 -258
  117. data/doc/Schemacop/NodeSupportingField.html +0 -590
  118. data/doc/Schemacop/NodeSupportingType.html +0 -612
  119. data/doc/Schemacop/NodeWithBlock.html +0 -289
  120. data/doc/Schemacop/NumberValidator.html +0 -232
  121. data/doc/Schemacop/ObjectValidator.html +0 -298
  122. data/doc/Schemacop/RootNode.html +0 -171
  123. data/doc/Schemacop/Schema.html +0 -699
  124. data/doc/Schemacop/StringValidator.html +0 -295
  125. data/doc/Schemacop/SymbolValidator.html +0 -145
  126. data/doc/ScopedEnv.html +0 -351
  127. data/doc/_index.html +0 -379
  128. data/doc/class_list.html +0 -51
  129. data/doc/css/common.css +0 -1
  130. data/doc/css/full_list.css +0 -58
  131. data/doc/css/style.css +0 -496
  132. data/doc/file.README.html +0 -833
  133. data/doc/file_list.html +0 -56
  134. data/doc/frames.html +0 -17
  135. data/doc/index.html +0 -833
  136. data/doc/inheritance.graphml +0 -524
  137. data/doc/inheritance.pdf +0 -825
  138. data/doc/js/app.js +0 -303
  139. data/doc/js/full_list.js +0 -216
  140. data/doc/js/jquery.js +0 -4
  141. data/doc/method_list.html +0 -587
  142. data/doc/top-level-namespace.html +0 -112
  143. data/lib/schemacop/node.rb +0 -139
  144. data/lib/schemacop/root_node.rb +0 -4
  145. data/lib/schemacop/validator/array_validator.rb +0 -30
  146. data/lib/schemacop/validator/float_validator.rb +0 -5
  147. data/lib/schemacop/validator/hash_validator.rb +0 -35
  148. data/lib/schemacop/validator/integer_validator.rb +0 -5
  149. data/lib/schemacop/validator/number_validator.rb +0 -19
  150. data/lib/schemacop/validator/object_validator.rb +0 -27
  151. data/lib/schemacop/validator/string_validator.rb +0 -37
  152. data/test/casting_test.rb +0 -118
  153. data/test/collector_test.rb +0 -45
  154. data/test/custom_check_test.rb +0 -93
  155. data/test/custom_if_test.rb +0 -95
  156. data/test/defaults_test.rb +0 -93
  157. data/test/empty_test.rb +0 -14
  158. data/test/nil_dis_allow_test.rb +0 -41
  159. data/test/node_resolver_test.rb +0 -26
  160. data/test/short_forms_test.rb +0 -349
  161. data/test/test_helper.rb +0 -13
  162. data/test/types_test.rb +0 -84
  163. data/test/validator_array_test.rb +0 -97
  164. data/test/validator_boolean_test.rb +0 -15
  165. data/test/validator_float_test.rb +0 -57
  166. data/test/validator_hash_test.rb +0 -93
  167. data/test/validator_integer_test.rb +0 -46
  168. data/test/validator_nil_test.rb +0 -13
  169. data/test/validator_number_test.rb +0 -60
  170. data/test/validator_object_test.rb +0 -139
  171. data/test/validator_string_test.rb +0 -76
  172. data/test/validator_symbol_test.rb +0 -16
@@ -1,56 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
5
- <meta charset="utf-8" />
6
-
7
- <link rel="stylesheet" href="css/full_list.css" type="text/css" media="screen" charset="utf-8" />
8
-
9
- <link rel="stylesheet" href="css/common.css" type="text/css" media="screen" charset="utf-8" />
10
-
11
-
12
-
13
- <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
14
-
15
- <script type="text/javascript" charset="utf-8" src="js/full_list.js"></script>
16
-
17
-
18
- <title>File List</title>
19
- <base id="base_target" target="_parent" />
20
- </head>
21
- <body>
22
- <div id="content">
23
- <div class="fixed_header">
24
- <h1 id="full_list_header">File List</h1>
25
- <div id="full_list_nav">
26
-
27
- <span><a target="_self" href="class_list.html">
28
- Classes
29
- </a></span>
30
-
31
- <span><a target="_self" href="method_list.html">
32
- Methods
33
- </a></span>
34
-
35
- <span><a target="_self" href="file_list.html">
36
- Files
37
- </a></span>
38
-
39
- </div>
40
-
41
- <div id="search">Search: <input type="text" /></div>
42
- </div>
43
-
44
- <ul id="full_list" class="file">
45
-
46
-
47
- <li id="object_README" class="odd">
48
- <div class="item"><span class="object_link"><a href="index.html" title="README">README</a></span></div>
49
- </li>
50
-
51
-
52
-
53
- </ul>
54
- </div>
55
- </body>
56
- </html>
@@ -1,17 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8">
5
- <title>Documentation by YARD 0.9.20</title>
6
- </head>
7
- <script type="text/javascript" charset="utf-8">
8
- var match = unescape(window.location.hash).match(/^#!(.+)/);
9
- var name = match ? match[1] : 'index.html';
10
- name = name.replace(/^(\w+):\/\//, '').replace(/^\/\//, '');
11
- window.top.location = name;
12
- </script>
13
- <noscript>
14
- <h1>Oops!</h1>
15
- <h2>YARD requires JavaScript!</h2>
16
- </noscript>
17
- </html>
@@ -1,833 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>
7
- File: README
8
-
9
- &mdash; Documentation by YARD 0.9.20
10
-
11
- </title>
12
-
13
- <link rel="stylesheet" href="css/style.css" type="text/css" charset="utf-8" />
14
-
15
- <link rel="stylesheet" href="css/common.css" type="text/css" charset="utf-8" />
16
-
17
- <script type="text/javascript" charset="utf-8">
18
- pathId = "README";
19
- relpath = '';
20
- </script>
21
-
22
-
23
- <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
24
-
25
- <script type="text/javascript" charset="utf-8" src="js/app.js"></script>
26
-
27
-
28
- </head>
29
- <body>
30
- <div class="nav_wrap">
31
- <iframe id="nav" src="class_list.html?1"></iframe>
32
- <div id="resizer"></div>
33
- </div>
34
-
35
- <div id="main" tabindex="-1">
36
- <div id="header">
37
- <div id="menu">
38
-
39
- <a href="_index.html">Index</a> &raquo;
40
- <span class="title">File: README</span>
41
-
42
- </div>
43
-
44
- <div id="search">
45
-
46
- <a class="full_list_link" id="class_list_link"
47
- href="class_list.html">
48
-
49
- <svg width="24" height="24">
50
- <rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
51
- <rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
52
- <rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
53
- </svg>
54
- </a>
55
-
56
- </div>
57
- <div class="clear"></div>
58
- </div>
59
-
60
- <div id="content"><div id='filecontents'><p><a href="https://travis-ci.org/sitrox/schemacop"><img src="https://travis-ci.org/sitrox/schemacop.svg?branch=master" alt="Build Status"></a>
61
- <a href="https://badge.fury.io/rb/schemacop"><img src="https://badge.fury.io/rb/schemacop.svg" alt="Gem Version"></a></p>
62
-
63
- <h1>Schemacop</h1>
64
-
65
- <p>This is the README for Schemacop version 2, which <strong>breaks backwards
66
- compatibility</strong> with version 1.</p>
67
-
68
- <p>Schemacop validates ruby structures consisting of nested hashes and arrays
69
- against schema definitions described by a simple DSL.</p>
70
-
71
- <p>Examples:</p>
72
-
73
- <pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_schema'>schema</span> <span class='op'>=</span> <span class='const'>Schema</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span> <span class='kw'>do</span>
74
- <span class='id identifier rubyid_req'>req</span> <span class='symbol'>:naming</span><span class='comma'>,</span> <span class='symbol'>:hash</span> <span class='kw'>do</span>
75
- <span class='id identifier rubyid_opt'>opt</span> <span class='symbol'>:first_name</span><span class='comma'>,</span> <span class='symbol'>:string</span>
76
- <span class='id identifier rubyid_req'>req</span> <span class='symbol'>:last_name</span><span class='comma'>,</span> <span class='symbol'>:string</span>
77
- <span class='kw'>end</span>
78
- <span class='id identifier rubyid_opt!'>opt!</span> <span class='symbol'>:age</span><span class='comma'>,</span> <span class='symbol'>:integer</span><span class='comma'>,</span> <span class='label'>min:</span> <span class='int'>18</span>
79
- <span class='id identifier rubyid_req?'>req?</span> <span class='symbol'>:password</span> <span class='kw'>do</span>
80
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:string</span><span class='comma'>,</span> <span class='label'>check:</span> <span class='id identifier rubyid_proc'>proc</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_pw'>pw</span><span class='op'>|</span> <span class='id identifier rubyid_pw'>pw</span><span class='period'>.</span><span class='id identifier rubyid_include?'>include?</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>*</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span> <span class='rbrace'>}</span>
81
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:integer</span>
82
- <span class='kw'>end</span>
83
- <span class='kw'>end</span>
84
-
85
- <span class='id identifier rubyid_schema'>schema</span><span class='period'>.</span><span class='id identifier rubyid_validate!'>validate!</span><span class='lparen'>(</span>
86
- <span class='label'>naming:</span> <span class='lbrace'>{</span> <span class='label'>first_name:</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>John</span><span class='tstring_end'>&#39;</span></span><span class='comma'>,</span>
87
- <span class='label'>last_name:</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>Doe</span><span class='tstring_end'>&#39;</span></span> <span class='rbrace'>}</span><span class='comma'>,</span>
88
- <span class='label'>age:</span> <span class='int'>34</span><span class='comma'>,</span>
89
- <span class='label'>password:</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>my*pass</span><span class='tstring_end'>&#39;</span></span>
90
- <span class='rparen'>)</span>
91
- </code></pre>
92
-
93
- <pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_schema2'>schema2</span> <span class='op'>=</span> <span class='const'>Schema</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span> <span class='kw'>do</span>
94
- <span class='id identifier rubyid_req'>req</span> <span class='symbol'>:description</span><span class='comma'>,</span>
95
- <span class='symbol'>:string</span><span class='comma'>,</span>
96
- <span class='label'>if:</span> <span class='id identifier rubyid_proc'>proc</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_str'>str</span><span class='op'>|</span> <span class='id identifier rubyid_str'>str</span><span class='period'>.</span><span class='id identifier rubyid_start_with?'>start_with?</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>Abstract: </span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span> <span class='rbrace'>}</span><span class='comma'>,</span>
97
- <span class='label'>max:</span> <span class='int'>35</span><span class='comma'>,</span>
98
- <span class='label'>check:</span> <span class='id identifier rubyid_proc'>proc</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_str'>str</span><span class='op'>|</span> <span class='op'>!</span><span class='id identifier rubyid_str'>str</span><span class='period'>.</span><span class='id identifier rubyid_end_with?'>end_with?</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>.</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span> <span class='rbrace'>}</span>
99
- <span class='id identifier rubyid_req'>req</span> <span class='symbol'>:description</span><span class='comma'>,</span> <span class='symbol'>:string</span><span class='comma'>,</span> <span class='label'>min:</span> <span class='int'>35</span>
100
- <span class='kw'>end</span>
101
-
102
- <span class='id identifier rubyid_schema2'>schema2</span><span class='period'>.</span><span class='id identifier rubyid_validate!'>validate!</span><span class='lparen'>(</span><span class='label'>description:</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>Abstract: a short description</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
103
- <span class='id identifier rubyid_schema2'>schema2</span><span class='period'>.</span><span class='id identifier rubyid_validate!'>validate!</span><span class='lparen'>(</span><span class='label'>description:</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>Since this is no abstract, we expect it to be longer.</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
104
- </code></pre>
105
-
106
- <h2>Installation</h2>
107
-
108
- <p>To install the <strong>Schemacop</strong> gem:</p>
109
-
110
- <pre class="code sh"><code class="sh">$ gem install schemacop
111
- </code></pre>
112
-
113
- <p>To install it using <code>bundler</code> (recommended for any application), add it to your
114
- <code>Gemfile</code>:</p>
115
-
116
- <pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_gem'>gem</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>schemacop</span><span class='tstring_end'>&#39;</span></span>
117
- </code></pre>
118
-
119
- <h2>Basics</h2>
120
-
121
- <p>Since there is no explicit typing in Ruby, it can be hard to make sure that a
122
- method is recieving exactly the right kind of data it needs. The idea of this
123
- gem is to define a schema at boot time that will validate the data being passed
124
- around at runtime. Those two steps look as follows:</p>
125
-
126
- <p>At boot time:</p>
127
-
128
- <pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_my_schema'>my_schema</span> <span class='op'>=</span> <span class='const'>Schema</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span> <span class='kw'>do</span>
129
- <span class='comment'># Your specification goes here
130
- </span><span class='kw'>end</span>
131
- </code></pre>
132
-
133
- <p>At runtime:</p>
134
-
135
- <pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_my_schema'>my_schema</span><span class='period'>.</span><span class='id identifier rubyid_validate!'>validate!</span><span class='lparen'>(</span>
136
- <span class='comment'># Your data goes here
137
- </span><span class='rparen'>)</span>
138
- </code></pre>
139
-
140
- <p><code>validate!</code> will fail if the data given to it does not match what was specified
141
- in the schema.</p>
142
-
143
- <h3>Type lines vs. Field lines</h3>
144
-
145
- <p>Schemacop uses a DSL (domain-specific language) to let you describe your
146
- schemas. We distinguish between two kinds of identifiers:</p>
147
-
148
- <ul>
149
- <li><p>Field Lines: We call a key-value pair (like the contents of a hash) a <em>field</em>.
150
- A field line typically starts with the keyword <code>req</code> (for a required field) or
151
- <code>opt</code> (for an optional field).</p></li>
152
- <li><p>Type Lines: Those start with the keyword <code>type</code> and specify the data type to
153
- be accepted with a corresponding symbol (e.g. <code>:integer</code> or <code>:boolean</code>). You
154
- can have multiple Type Lines for a Field Line in order to indicate that the
155
- field&#39;s value can be of one of the specified types.</p></li>
156
- </ul>
157
-
158
- <p>If you don&#39;t use any short forms, a schema definition would be something like
159
- this:</p>
160
-
161
- <pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_s'>s</span> <span class='op'>=</span> <span class='const'>Schema</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span> <span class='kw'>do</span>
162
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:integer</span>
163
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:hash</span> <span class='kw'>do</span>
164
- <span class='id identifier rubyid_req'>req</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>present</span><span class='tstring_end'>&#39;</span></span> <span class='kw'>do</span>
165
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:boolean</span>
166
- <span class='kw'>end</span>
167
- <span class='kw'>end</span>
168
- <span class='kw'>end</span>
169
- </code></pre>
170
-
171
- <p>The above schema would accept either an integer or a hash with exactly one field
172
- with key &#39;present&#39; of type String and value of type Boolean (either TrueClass or
173
- FalseClass).</p>
174
-
175
- <p>We will see Type and Field lines in more detail below.</p>
176
-
177
- <h3><code>validate</code> vs <code>validate!</code> vs <code>valid?</code></h3>
178
-
179
- <p>The method <code>validate</code> will return a <code>Collector</code> object that contains all
180
- validation errors (if any) as well as a deep copy of your data with applied
181
- defaults and castings, whereas <code>validate!</code> will accumulate all violations
182
- and finally throw an exception describing them or, if the validation was
183
- successful, a deep-copy of your supplied data with defaults and castings
184
- applied.</p>
185
-
186
- <p>For simply querying the validity of some data, use the methods <code>valid?</code> or
187
- <code>invalid?</code>.</p>
188
-
189
- <p>Examples:</p>
190
-
191
- <pre class="code ruby"><code class="ruby"><span class='comment'># validate! returns your modified data or throws a validation error
192
- </span><span class='id identifier rubyid_s'>s</span> <span class='op'>=</span> <span class='const'>Schema</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span> <span class='kw'>do</span>
193
- <span class='id identifier rubyid_req'>req</span> <span class='symbol'>:foo</span><span class='comma'>,</span> <span class='label'>default:</span> <span class='int'>42</span>
194
- <span class='kw'>end</span>
195
- <span class='id identifier rubyid_s'>s</span><span class='period'>.</span><span class='id identifier rubyid_validate!'>validate!</span><span class='lparen'>(</span><span class='lbrace'>{</span><span class='rbrace'>}</span><span class='rparen'>)</span> <span class='comment'># =&gt; { foo: 42 }
196
- </span>
197
- <span class='comment'># validate returns a collector
198
- </span><span class='id identifier rubyid_s'>s</span> <span class='op'>=</span> <span class='const'>Schema</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span> <span class='kw'>do</span>
199
- <span class='id identifier rubyid_req'>req</span> <span class='symbol'>:foo</span><span class='comma'>,</span> <span class='label'>default:</span> <span class='int'>42</span>
200
- <span class='kw'>end</span>
201
-
202
- <span class='id identifier rubyid_collector'>collector</span> <span class='op'>=</span> <span class='id identifier rubyid_s'>s</span><span class='period'>.</span><span class='id identifier rubyid_validate'>validate</span><span class='lparen'>(</span><span class='lbrace'>{</span><span class='rbrace'>}</span><span class='rparen'>)</span>
203
- <span class='id identifier rubyid_collector'>collector</span><span class='period'>.</span><span class='id identifier rubyid_valid?'>valid?</span> <span class='comment'># true
204
- </span><span class='id identifier rubyid_collector'>collector</span><span class='period'>.</span><span class='id identifier rubyid_data'>data</span> <span class='comment'># =&gt; { foo: 42 }
205
- </span>
206
- <span class='id identifier rubyid_collector'>collector</span> <span class='op'>=</span> <span class='id identifier rubyid_s'>s</span><span class='period'>.</span><span class='id identifier rubyid_validate'>validate</span><span class='lparen'>(</span><span class='lbrace'>{</span> <span class='label'>foo:</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>invalid</span><span class='tstring_end'>&#39;</span></span> <span class='rbrace'>}</span><span class='rparen'>)</span>
207
- <span class='id identifier rubyid_collector'>collector</span><span class='period'>.</span><span class='id identifier rubyid_valid?'>valid?</span> <span class='comment'># false
208
- </span><span class='id identifier rubyid_collector'>collector</span><span class='period'>.</span><span class='id identifier rubyid_data'>data</span> <span class='comment'># =&gt; nil
209
- </span><span class='id identifier rubyid_collector'>collector</span><span class='period'>.</span><span class='id identifier rubyid_exceptions'>exceptions</span> <span class='comment'># =&gt; Validation error
210
- </span></code></pre>
211
-
212
- <h2>Schemacop&#39;s DSL</h2>
213
-
214
- <p>In this section, we will ignore <a href="#short-forms">short forms</a> and explicitly
215
- write out everything.</p>
216
-
217
- <p>Inside the block given at the schema instantiation (<code>Schema.new do ... end</code>),
218
- the following kinds of method calls are allowed (where the outermost must be a
219
- Type Line):</p>
220
-
221
- <h3>Type Line</h3>
222
-
223
- <p>A Type Line always starts with the identifier <code>type</code> and specifies a possible
224
- data type for a given field (if inside a Field Line) or the given data structure
225
- (if directly below the schema instantiation).</p>
226
-
227
- <p>Type Lines are generally of the form</p>
228
-
229
- <pre class="code ruby"><code class="ruby">type :my_type, option_1: value_1, ..., option_n: value_n
230
- </code></pre>
231
-
232
- <p>where <code>:my_type</code> is a supported symbol (see section <a href="#types">Types</a> below for
233
- supported types).</p>
234
-
235
- <h4>General options</h4>
236
-
237
- <p>Some types support specific options that allow additional checks on the nature
238
- of the data (such as the <code>min</code> option for type <code>:number</code>). The following options
239
- are supported by all types:</p>
240
-
241
- <h5>Option <code>if</code></h5>
242
-
243
- <p>This option takes a proc (or a lambda) as value. The proc will be called when
244
- checking whether or not the data being analyzed fits a certain type. The data is
245
- given to the proc, which has to return either true or false. If it returns true,
246
- the type of the given data is considered correct and the data will be validated
247
- if further options are given.</p>
248
-
249
- <p>Note that the proc in <code>if</code> will only get called if the type (<code>:my_type</code> from
250
- above) fits the data already. You can use the option <code>if</code> in order to say: &quot;Even
251
- if the data is of type <code>:my_type</code>, I consider it having the wrong type if my
252
- proc returns false.&quot;</p>
253
-
254
- <p>Consider a scenario in which you want to have the following rule set:</p>
255
-
256
- <ul>
257
- <li>Only integers may be given</li>
258
- <li>Odd integers must be no larger than 15</li>
259
- <li>No limitations for even integers</li>
260
- </ul>
261
-
262
- <p>The corresponding schema would look as follows:</p>
263
-
264
- <pre class="code ruby"><code class="ruby"><span class='const'>Schema</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span> <span class='kw'>do</span>
265
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:integer</span><span class='comma'>,</span> <span class='label'>if:</span> <span class='id identifier rubyid_proc'>proc</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_data'>data</span><span class='op'>|</span> <span class='id identifier rubyid_data'>data</span><span class='period'>.</span><span class='id identifier rubyid_odd?'>odd?</span> <span class='rbrace'>}</span><span class='comma'>,</span> <span class='label'>max:</span> <span class='int'>15</span>
266
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:integer</span>
267
- <span class='kw'>end</span>
268
- </code></pre>
269
-
270
- <p>Here, the first type line will only accept odd numbers and the option <code>max: 15</code>
271
- provided by the <code>:integer</code> validator will discard numbers higher than 15.</p>
272
-
273
- <p>Since the first line only accepts odd numbers, it doesn&#39;t apply for even numbers
274
- (due to the proc given to <code>if</code> they are considered to be of the wrong type) and
275
- control falls through to the second type line accepting any integer.</p>
276
-
277
- <h5>Option <code>check</code></h5>
278
-
279
- <p>This option allows you to perform arbitrary custom checks for a given data type.
280
- Just like <code>if</code>, <code>check</code> takes a proc or lambda as a value, but it runs <em>after</em>
281
- the type checking, meaning that it only gets executed if the data has the right
282
- type and the proc in <code>if</code> (if any) has returned true.</p>
283
-
284
- <p>The proc passed to the <code>check</code> option is given the data being analyzed. It is to
285
- return true if the data passes the custom check. If it returns false or an error
286
- message as a string, Schemacop considers the data to be invalid.</p>
287
-
288
- <p>The following example illustrates the use of the option <code>check</code>: Consider a
289
- scenario in which you want the following rule set:</p>
290
-
291
- <ul>
292
- <li>Data must be of type String</li>
293
- <li>The string must be longer than 5 characters</li>
294
- <li>The second character must be an &#39;r&#39;</li>
295
- </ul>
296
-
297
- <p>The corresponding schema would look as follows:</p>
298
-
299
- <pre class="code ruby"><code class="ruby"><span class='const'>Schema</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span> <span class='kw'>do</span>
300
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:string</span><span class='comma'>,</span> <span class='label'>min:</span> <span class='int'>5</span><span class='comma'>,</span> <span class='label'>check:</span> <span class='id identifier rubyid_proc'>proc</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_data'>data</span><span class='op'>|</span> <span class='id identifier rubyid_data'>data</span><span class='lbracket'>[</span><span class='int'>1</span><span class='rbracket'>]</span> <span class='op'>==</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>r</span><span class='tstring_end'>&#39;</span></span><span class='rbrace'>}</span>
301
- <span class='kw'>end</span>
302
- </code></pre>
303
-
304
- <p>The above Type Line has type <code>:string</code> and two options (<code>min</code> and <code>check</code>). The
305
- option <code>min</code> is supported by the <code>:string</code> validator (covered later).</p>
306
-
307
- <p>You can also specify a custom error message by returning a string:</p>
308
-
309
- <pre class="code ruby"><code class="ruby"><span class='const'>Schema</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span> <span class='kw'>do</span>
310
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:integer</span><span class='comma'>,</span> <span class='label'>check:</span> <span class='id identifier rubyid_proc'>proc</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_i'>i</span><span class='op'>|</span> <span class='id identifier rubyid_i'>i</span><span class='period'>.</span><span class='id identifier rubyid_even?'>even?</span> <span class='op'>?</span> <span class='kw'>true</span> <span class='op'>:</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>Custom error</span><span class='tstring_end'>&#39;</span></span> <span class='rbrace'>}</span>
311
- <span class='kw'>end</span>
312
- </code></pre>
313
-
314
- <p>This will include <code>Custom error</code> in the validation error message.</p>
315
-
316
- <h3>Field Line</h3>
317
-
318
- <p>Inside a Type Line of type <code>:hash</code>, you may specify an arbitrary number of field
319
- lines (one for each key-value pair you want to be in the hash).</p>
320
-
321
- <p>Field Lines start with one of the following six identifiers: <code>req</code>, <code>req?</code>,
322
- <code>req!</code>, <code>opt</code>, <code>opt?</code> or <code>opt!</code>:</p>
323
-
324
- <ul>
325
- <li><p>The suffix <code>-!</code> means that the field must not be nil.</p></li>
326
- <li><p>The suffix <code>-?</code> means that the field may be nil.</p></li>
327
- <li><p>The prefix <code>req-</code> denotes a required field (validation fails if the given data
328
- hash doesn&#39;t define it). <code>req</code> is a shorthand notation for <code>req!</code> (meaning
329
- that by default, a required field cannot be nil).</p></li>
330
- <li><p>The prefix <code>opt-</code> denotes an optional field. <code>opt</code> is a shorthand notation for
331
- <code>opt?</code> (meaning that by default, an optional field may be nil).</p></li>
332
- </ul>
333
-
334
- <p>To summarize:</p>
335
-
336
- <ul>
337
- <li><code>req</code> or <code>req!</code>: required and non-nil</li>
338
- <li><code>req?</code>: required but may be nil</li>
339
- <li><code>opt</code> or <code>opt?</code>: optional and may be nil</li>
340
- <li><code>opt!</code>: optional but non-nil</li>
341
- </ul>
342
-
343
- <p>You then pass a block with a single or multiple Type Lines to the field.</p>
344
-
345
- <p>Example: The following schema defines a hash that has a required non-nil field
346
- of type String under the key <code>:name</code> (of type Symbol) and an optional but
347
- non-nil field of type Integer or Date under the key <code>:age</code>.</p>
348
-
349
- <pre class="code ruby"><code class="ruby"><span class='const'>Schema</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span> <span class='kw'>do</span>
350
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:hash</span> <span class='kw'>do</span>
351
- <span class='id identifier rubyid_req'>req</span> <span class='symbol'>:name</span> <span class='kw'>do</span>
352
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:string</span>
353
- <span class='kw'>end</span>
354
- <span class='id identifier rubyid_opt!'>opt!</span> <span class='symbol'>:age</span> <span class='kw'>do</span>
355
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:integer</span>
356
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:object</span><span class='comma'>,</span> <span class='label'>classes:</span> <span class='const'>Date</span>
357
- <span class='kw'>end</span>
358
- <span class='kw'>end</span>
359
- <span class='kw'>end</span>
360
- </code></pre>
361
-
362
- <p>You might find the notation cumbersome, and you&#39;d be right to say so. Luckily
363
- there are plenty of short forms available which we will see below.</p>
364
-
365
- <h4>Handling hashes with indifferent access</h4>
366
-
367
- <p>Schemacop has special handling for objects of the class
368
- <code>ActiveSupport::HashWithIndifferentAccess</code>: You may specify the keys as symbols
369
- or strings, and Schemacop will handle the conversion necessary for proper
370
- validation internally. Note that if you define the same key as string and
371
- symbol, it will throw a <code>ValidationError</code> <a href="#exceptions">exception</a> when asked to
372
- validate a hash with indifferent access.</p>
373
-
374
- <p>Thus, the following two schema definitions are equivalent when validating a hash
375
- with indifferent access:</p>
376
-
377
- <pre class="code ruby"><code class="ruby"><span class='const'>Schema</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span> <span class='kw'>do</span>
378
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:hash</span> <span class='kw'>do</span>
379
- <span class='id identifier rubyid_req'>req</span> <span class='symbol'>:name</span> <span class='kw'>do</span>
380
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:string</span>
381
- <span class='kw'>end</span>
382
- <span class='kw'>end</span>
383
- <span class='kw'>end</span>
384
-
385
- <span class='const'>Schema</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span> <span class='kw'>do</span>
386
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:hash</span> <span class='kw'>do</span>
387
- <span class='id identifier rubyid_req'>req</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>name</span><span class='tstring_end'>&#39;</span></span> <span class='kw'>do</span>
388
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:string</span>
389
- <span class='kw'>end</span>
390
- <span class='kw'>end</span>
391
- <span class='kw'>end</span>
392
- </code></pre>
393
-
394
- <h2>Types</h2>
395
-
396
- <p>Types are defined via their validators, which is a class under <code>validator/</code>.
397
- Each validator is sourced by <code>schemacop.rb</code>.</p>
398
-
399
- <p>The following types are supported by Schemacop by default:</p>
400
-
401
- <ul>
402
- <li><p><code>:boolean</code> accepts a Ruby TrueClass or FalseClass instance.</p></li>
403
- <li><p><code>:integer</code> accepts a Ruby Integer.</p>
404
-
405
- <ul>
406
- <li>supported options: <code>min</code>, <code>max</code> (lower / upper bound)</li>
407
- </ul></li>
408
- <li><p><code>:float</code> accepts a Ruby Float.</p>
409
-
410
- <ul>
411
- <li>supported options: <code>min</code>, <code>max</code> (lower / upper bound)</li>
412
- </ul></li>
413
- <li><p><code>:number</code> accepts a Ruby Integer or Float.</p>
414
-
415
- <ul>
416
- <li>supported options: <code>min</code>, <code>max</code> (lower / upper bound)</li>
417
- </ul></li>
418
- <li><p><code>:string</code> accepts a Ruby String.</p>
419
-
420
- <ul>
421
- <li>supported options: <code>min</code>, <code>max</code> (bounds for string length)</li>
422
- </ul></li>
423
- <li><p><code>:symbol</code> accepts a Ruby Symbol.</p></li>
424
- <li><p><code>:object</code> accepts an arbitrary Ruby object (any object if no option is given).</p></li>
425
- </ul>
426
-
427
- <p>Supported options:</p>
428
-
429
- <ul>
430
- <li><p><code>classes</code>: Ruby class (or an array of them) that will be the only recognized
431
- filters. Unlike other options, this one affects not the validation but the
432
- type recognition, meaning that you can have multiple Type Lines with
433
- different <code>classes</code> option for the same field, each having its own
434
- validation (e.g. through the option <code>check</code>).</p></li>
435
- <li><p><code>strict</code>: Boolean option, defaults to true. If set to false, the validator
436
- also allows derived classes of those specified with <code>classes</code>.</p>
437
-
438
- <ul>
439
- <li><code>:array</code> accepts a Ruby Array.</li>
440
- </ul></li>
441
- <li><p>supported options: <code>min</code>, <code>max</code> (bounds for array size) and <code>nil</code>: TODO</p></li>
442
- <li><p>accepts a block with an arbitrary number of Type Lines.</p></li>
443
- <li><p>TODO no lookahead for different arrays, see
444
- validator_array_test#test_multiple_arrays</p>
445
-
446
- <ul>
447
- <li><code>:hash</code> accepts a Ruby Hash or an <code>ActiveSupport::HashWithIndifferentAccess</code>.</li>
448
- </ul></li>
449
- <li><p>accepts a block with an arbitrary number of Field Lines.</p></li>
450
- <li><p><code>allow_obsolete_keys</code>: If enabled (default <code>false</code>), this allows arbitrary
451
- keys within your hash. Keys not specified in your schema will not be
452
- validated further, but keys specified explicitly are still validated.</p>
453
-
454
- <ul>
455
- <li><code>:nil</code>: accepts a Ruby NilClass instance. If you want to allow <code>nil</code> as a
456
- value in a field, see above for the usage of the suffixes <code>-!</code> and <code>-?</code> for
457
- Field Lines.</li>
458
- </ul></li>
459
- </ul>
460
-
461
- <p>All types support the options <code>if</code> and <code>check</code> (see the section about Type Lines
462
- above).</p>
463
-
464
- <h2>Short forms</h2>
465
-
466
- <p>For convenience, the following short forms may be used (and combined if
467
- possible).</p>
468
-
469
- <h3>Passing a type to a Field Line or schema</h3>
470
-
471
- <p>Instead of adding a Type Line in the block of a Field Line, you can omit <code>do
472
- type ... end</code> and directly write the type after the key of the field.</p>
473
-
474
- <p>Note that when using this short form, you may not give a block to the Field
475
- Line.</p>
476
-
477
- <pre class="code ruby"><code class="ruby"><span class='comment'># Long form
478
- </span><span class='id identifier rubyid_req'>req</span> <span class='symbol'>:name</span> <span class='kw'>do</span>
479
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:string</span><span class='comma'>,</span> <span class='label'>min:</span> <span class='int'>2</span><span class='comma'>,</span> <span class='label'>max:</span> <span class='int'>5</span>
480
- <span class='kw'>end</span>
481
-
482
- <span class='comment'># Short form
483
- </span><span class='id identifier rubyid_req'>req</span> <span class='symbol'>:name</span><span class='comma'>,</span> <span class='symbol'>:string</span><span class='comma'>,</span> <span class='label'>min:</span> <span class='int'>2</span><span class='comma'>,</span> <span class='label'>max:</span> <span class='int'>5</span>
484
- </code></pre>
485
-
486
- <p>This means that the value under the key <code>:name</code> of type Symbol must be a String
487
- containing 2 to 5 characters.</p>
488
-
489
- <p>The short form also works in the schema instantiation:</p>
490
-
491
- <pre class="code ruby"><code class="ruby"><span class='comment'># Long form
492
- </span><span class='const'>Schema</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span> <span class='kw'>do</span>
493
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:string</span><span class='comma'>,</span> <span class='label'>min:</span> <span class='int'>2</span><span class='comma'>,</span> <span class='label'>max:</span> <span class='int'>5</span>
494
- <span class='kw'>end</span>
495
-
496
- <span class='comment'># Short form
497
- </span><span class='const'>Schema</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span><span class='lparen'>(</span><span class='symbol'>:string</span><span class='comma'>,</span> <span class='label'>min:</span> <span class='int'>2</span><span class='comma'>,</span> <span class='label'>max:</span> <span class='int'>5</span><span class='rparen'>)</span>
498
- </code></pre>
499
-
500
- <p>This means that the data given to the schema must be a String that is between 2
501
- and 5 characters long.</p>
502
-
503
- <h3>Passing multiple types at once</h3>
504
-
505
- <p>You can specify several types at once by putting them in an array.</p>
506
-
507
- <p>Note that when using this short form, you may not give any options.</p>
508
-
509
- <pre class="code ruby"><code class="ruby"><span class='comment'># Long form
510
- </span><span class='id identifier rubyid_opt!'>opt!</span> <span class='symbol'>:age</span> <span class='kw'>do</span>
511
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:string</span>
512
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:integer</span>
513
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:boolean</span>
514
- <span class='kw'>end</span>
515
-
516
- <span class='comment'># Short form
517
- </span><span class='id identifier rubyid_opt!'>opt!</span> <span class='symbol'>:age</span> <span class='kw'>do</span>
518
- <span class='id identifier rubyid_type'>type</span> <span class='lbracket'>[</span><span class='symbol'>:string</span><span class='comma'>,</span> <span class='symbol'>:integer</span><span class='comma'>,</span> <span class='symbol'>:boolean</span><span class='rbracket'>]</span>
519
- <span class='kw'>end</span>
520
- </code></pre>
521
-
522
- <p>Combined with previous short form:</p>
523
-
524
- <pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_opt!'>opt!</span> <span class='symbol'>:age</span><span class='comma'>,</span> <span class='lbracket'>[</span><span class='symbol'>:string</span><span class='comma'>,</span> <span class='symbol'>:integer</span><span class='comma'>,</span> <span class='symbol'>:boolean</span><span class='rbracket'>]</span>
525
- </code></pre>
526
-
527
- <p>This also works in the schema instantiation:</p>
528
-
529
- <pre class="code ruby"><code class="ruby"><span class='const'>Schema</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span><span class='lparen'>(</span><span class='lbracket'>[</span><span class='symbol'>:string</span><span class='comma'>,</span> <span class='symbol'>:integer</span><span class='comma'>,</span> <span class='symbol'>:boolean</span><span class='rbracket'>]</span><span class='rparen'>)</span>
530
- </code></pre>
531
-
532
- <p>This means that the schema will validate any data of type String, Integer,
533
- TrueClass or FalseClass.</p>
534
-
535
- <h3>Omitting the Type Line in a Field Line</h3>
536
-
537
- <p>If you don&#39;t specify the type of a field, it will default to <code>:object</code> with no
538
- options, meaning that the field will accept any kind of data:</p>
539
-
540
- <pre class="code ruby"><code class="ruby"><span class='comment'># Long form
541
- </span><span class='id identifier rubyid_req?'>req?</span> <span class='symbol'>:child</span> <span class='kw'>do</span>
542
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:object</span>
543
- <span class='kw'>end</span>
544
-
545
- <span class='comment'># Short form
546
- </span><span class='id identifier rubyid_req?'>req?</span> <span class='symbol'>:child</span>
547
- </code></pre>
548
-
549
- <h3>Omitting the Type Line in schema instantiation</h3>
550
-
551
- <p>If you don&#39;t give a Type Line to a schema, it will accept data of type Hash.
552
- Therefore, if you validate Hashes only, you can omit the Type Line and directly
553
- write Field Lines in the schema instantiation:</p>
554
-
555
- <pre class="code ruby"><code class="ruby"><span class='comment'># Long form
556
- </span><span class='const'>Schema</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span> <span class='kw'>do</span>
557
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:hash</span> <span class='kw'>do</span>
558
- <span class='id identifier rubyid_req'>req</span> <span class='symbol'>:name</span> <span class='kw'>do</span>
559
- <span class='comment'># ...
560
- </span> <span class='kw'>end</span>
561
- <span class='kw'>end</span>
562
- <span class='kw'>end</span>
563
-
564
- <span class='comment'># Short form
565
- </span><span class='const'>Schema</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span> <span class='kw'>do</span>
566
- <span class='id identifier rubyid_req'>req</span> <span class='symbol'>:name</span> <span class='kw'>do</span>
567
- <span class='comment'># ...
568
- </span> <span class='kw'>end</span>
569
- <span class='kw'>end</span>
570
- </code></pre>
571
-
572
- <p>Note that this does not allow you to specify any options for the hash itself.
573
- You still need to specify <code>:hash</code> as a type if you want to pass any options to
574
- the hash (i.e. a <code>default</code>).</p>
575
-
576
- <h3>Shortform for subtypes</h3>
577
-
578
- <p>In case of nested arrays, you can group all Type Lines to a single one.</p>
579
-
580
- <p>Note that any options or block passed to the grouped Type Line will be given to
581
- the innermost (last) type.</p>
582
-
583
- <pre class="code ruby"><code class="ruby"><span class='comment'># Long form
584
- </span><span class='id identifier rubyid_type'>type</span> <span class='symbol'>:array</span> <span class='kw'>do</span>
585
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:integer</span><span class='comma'>,</span> <span class='label'>min:</span> <span class='int'>3</span>
586
- <span class='kw'>end</span>
587
-
588
- <span class='comment'># Short form
589
- </span><span class='id identifier rubyid_type'>type</span> <span class='symbol'>:array</span><span class='comma'>,</span> <span class='symbol'>:integer</span><span class='comma'>,</span> <span class='label'>min:</span> <span class='int'>3</span>
590
- </code></pre>
591
-
592
- <p>A more complex example:</p>
593
-
594
- <p>Long form:</p>
595
-
596
- <pre class="code ruby"><code class="ruby"><span class='const'>Schema</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span> <span class='kw'>do</span>
597
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:hash</span> <span class='kw'>do</span>
598
- <span class='id identifier rubyid_req'>req</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>nutrition</span><span class='tstring_end'>&#39;</span></span> <span class='kw'>do</span>
599
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:array</span> <span class='kw'>do</span>
600
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:array</span> <span class='kw'>do</span>
601
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:hash</span><span class='comma'>,</span> <span class='label'>check:</span> <span class='id identifier rubyid_proc'>proc</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_h'>h</span><span class='op'>|</span> <span class='id identifier rubyid_h'>h</span><span class='period'>.</span><span class='id identifier rubyid_member?'>member?</span><span class='lparen'>(</span><span class='symbol'>:food</span><span class='rparen'>)</span> <span class='op'>||</span> <span class='id identifier rubyid_h'>h</span><span class='period'>.</span><span class='id identifier rubyid_member?'>member?</span><span class='lparen'>(</span><span class='symbol'>:drink</span><span class='rparen'>)</span> <span class='rbrace'>}</span> <span class='kw'>do</span>
602
- <span class='id identifier rubyid_opt!'>opt!</span> <span class='symbol'>:food</span> <span class='kw'>do</span>
603
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:object</span>
604
- <span class='kw'>end</span>
605
- <span class='id identifier rubyid_opt!'>opt!</span> <span class='symbol'>:drink</span> <span class='kw'>do</span>
606
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:object</span>
607
- <span class='kw'>end</span>
608
- <span class='kw'>end</span>
609
- <span class='kw'>end</span>
610
- <span class='kw'>end</span>
611
- <span class='kw'>end</span>
612
- <span class='kw'>end</span>
613
- <span class='kw'>end</span>
614
- </code></pre>
615
-
616
- <p>Short form (with this short form others from above):</p>
617
-
618
- <pre class="code ruby"><code class="ruby"><span class='const'>Schema</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span> <span class='kw'>do</span>
619
- <span class='id identifier rubyid_req'>req</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>nutrition</span><span class='tstring_end'>&#39;</span></span><span class='comma'>,</span> <span class='symbol'>:array</span><span class='comma'>,</span> <span class='symbol'>:array</span><span class='comma'>,</span> <span class='symbol'>:hash</span><span class='comma'>,</span> <span class='label'>check:</span> <span class='id identifier rubyid_proc'>proc</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_h'>h</span><span class='op'>|</span> <span class='id identifier rubyid_h'>h</span><span class='period'>.</span><span class='id identifier rubyid_member?'>member?</span><span class='lparen'>(</span><span class='symbol'>:food</span><span class='rparen'>)</span> <span class='op'>||</span> <span class='id identifier rubyid_h'>h</span><span class='period'>.</span><span class='id identifier rubyid_member?'>member?</span><span class='lparen'>(</span><span class='symbol'>:drink</span><span class='rparen'>)</span> <span class='rbrace'>}</span> <span class='kw'>do</span>
620
- <span class='id identifier rubyid_opt!'>opt!</span> <span class='symbol'>:food</span>
621
- <span class='id identifier rubyid_opt!'>opt!</span> <span class='symbol'>:drink</span>
622
- <span class='kw'>end</span>
623
- <span class='kw'>end</span>
624
- </code></pre>
625
-
626
- <p>This example accepts a hash with exactly one String key &#39;nutrition&#39; with value
627
- of type Array with children of type Array with children of type Hash in which at
628
- least one of the Symbol keys <code>:food</code> and <code>:drink</code> (with any non-nil value type)
629
- is present.</p>
630
-
631
- <h2>Defaults</h2>
632
-
633
- <p>Starting from version 2.4.0, Schemacop allows you to define default values at
634
- any point in your schema. If the validated data contains a nil value, it will be
635
- substituted by the given default value.</p>
636
-
637
- <p>Note that Schemacop never modifies the data you pass to it. If you want to
638
- benefit from Schemacop-applied defaults, you need to access the cloned, modified
639
- data returned by <code>validate</code> or <code>validate!</code>.</p>
640
-
641
- <p>Applying defaults is done before validating the substructure and before any type
642
- casting. The provided default will be validated same as user-supplied data, so
643
- if your given default does not validate properly, a validation error is thrown.
644
- Make sure your default values always match the underlying schema.</p>
645
-
646
- <p>Defaults can be specified at any point:</p>
647
-
648
- <pre class="code ruby"><code class="ruby"><span class='comment'># Basic usage
649
- </span><span class='const'>Schema</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span> <span class='kw'>do</span>
650
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:string</span><span class='comma'>,</span> <span class='label'>default:</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>Hello World</span><span class='tstring_end'>&#39;</span></span>
651
- <span class='kw'>end</span>
652
-
653
- <span class='comment'># The default given for the first type will match
654
- </span><span class='const'>Schema</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span> <span class='kw'>do</span>
655
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:string</span><span class='comma'>,</span> <span class='label'>default:</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>Hello World</span><span class='tstring_end'>&#39;</span></span> <span class='comment'># This will always be applied of no value is supplied
656
- </span> <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:integer</span><span class='comma'>,</span> <span class='label'>default:</span> <span class='int'>42</span>
657
- <span class='kw'>end</span>
658
-
659
- <span class='comment'># You can also pass entire hashes or arrays to your defaults
660
- </span><span class='const'>Schema</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span> <span class='kw'>do</span>
661
- <span class='id identifier rubyid_req'>req</span> <span class='symbol'>:foo</span><span class='comma'>,</span> <span class='symbol'>:hash</span><span class='comma'>,</span> <span class='label'>default:</span> <span class='lbrace'>{</span> <span class='label'>foo:</span> <span class='symbol'>:bar</span> <span class='rbrace'>}</span> <span class='kw'>do</span>
662
- <span class='id identifier rubyid_req'>req</span> <span class='symbol'>:foo</span><span class='comma'>,</span> <span class='symbol'>:symbol</span>
663
- <span class='kw'>end</span>
664
- <span class='id identifier rubyid_req'>req</span> <span class='symbol'>:bar</span><span class='comma'>,</span> <span class='symbol'>:array</span><span class='comma'>,</span> <span class='symbol'>:integer</span><span class='comma'>,</span> <span class='label'>default:</span> <span class='lbracket'>[</span><span class='int'>1</span><span class='comma'>,</span> <span class='int'>2</span><span class='comma'>,</span> <span class='int'>3</span><span class='rbracket'>]</span>
665
- <span class='kw'>end</span>
666
-
667
- <span class='comment'># Defaults must match the given schema. The following will fail.
668
- </span><span class='const'>Schema</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span> <span class='kw'>do</span>
669
- <span class='id identifier rubyid_req'>req</span> <span class='symbol'>:foo</span><span class='comma'>,</span> <span class='label'>default:</span> <span class='lbrace'>{</span> <span class='label'>bar:</span> <span class='symbol'>:baz</span> <span class='rbrace'>}</span> <span class='kw'>do</span>
670
- <span class='id identifier rubyid_req'>req</span> <span class='symbol'>:foo</span>
671
- <span class='kw'>end</span>
672
- <span class='kw'>end</span>
673
-
674
- <span class='comment'># You can also specify blocks (without params) as defaults that will be
675
- </span><span class='comment'># evaluated at time of validation.
676
- </span><span class='const'>Schema</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span> <span class='kw'>do</span>
677
- <span class='id identifier rubyid_opt'>opt</span> <span class='symbol'>:year</span><span class='comma'>,</span> <span class='symbol'>:integer</span><span class='comma'>,</span> <span class='label'>default:</span> <span class='tlambda'>-&gt;</span><span class='lparen'>(</span><span class='rparen'>)</span> <span class='tlambeg'>{</span> <span class='const'>Time</span><span class='period'>.</span><span class='id identifier rubyid_now'>now</span><span class='period'>.</span><span class='id identifier rubyid_year'>year</span> <span class='rbrace'>}</span>
678
- <span class='kw'>end</span>
679
-
680
- <span class='comment'># If, for some very specific reason, you *need* the default to be an actual
681
- </span><span class='comment'># proc, wrap it inside another proc.
682
- </span><span class='const'>Schema</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span> <span class='kw'>do</span>
683
- <span class='id identifier rubyid_opt'>opt</span> <span class='symbol'>:myproc</span><span class='comma'>,</span> <span class='const'>Proc</span><span class='comma'>,</span> <span class='label'>default:</span> <span class='tlambda'>-&gt;</span><span class='lparen'>(</span><span class='rparen'>)</span> <span class='tlambeg'>{</span> <span class='tlambda'>-&gt;</span><span class='lparen'>(</span><span class='rparen'>)</span> <span class='tlambeg'>{</span> <span class='int'>42</span> <span class='rbrace'>}</span> <span class='rbrace'>}</span>
684
- <span class='kw'>end</span>
685
- </code></pre>
686
-
687
- <h3>Required data points</h3>
688
-
689
- <p>Note that any <em>required</em> validation is done before applying the defaults. If you
690
- specify a <code>req</code> field, it must always be given, no matter if you have specified
691
- a default or not. Therefore, specifying <code>req</code> fields do not make sense in
692
- conjunction with defaults, as the default is always ignored.</p>
693
-
694
- <h2>Type casting</h2>
695
-
696
- <p>Starting from version 2.4.0, Schemacop allows you to specify type castings that
697
- can alter the validated data. Consider the following:</p>
698
-
699
- <pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_s'>s</span> <span class='op'>=</span> <span class='const'>Schema</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span> <span class='kw'>do</span>
700
- <span class='id identifier rubyid_req'>req</span> <span class='symbol'>:id</span><span class='comma'>,</span> <span class='symbol'>:integer</span><span class='comma'>,</span> <span class='label'>cast:</span> <span class='lbracket'>[</span><span class='const'>String</span><span class='rbracket'>]</span>
701
- <span class='kw'>end</span>
702
-
703
- <span class='id identifier rubyid_data'>data</span> <span class='op'>=</span> <span class='id identifier rubyid_s'>s</span><span class='period'>.</span><span class='id identifier rubyid_validate!'>validate!</span><span class='lparen'>(</span><span class='label'>id:</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>42</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
704
- <span class='id identifier rubyid_data'>data</span> <span class='comment'># =&gt; { id: 42 }
705
- </span></code></pre>
706
-
707
- <p>Note that Schemacop never modifies the data you pass to it. If you want to
708
- benefit from Schemacop-applied castings, you need to access the cloned, modified
709
- data returned by <code>validate</code> or <code>validate!</code>.</p>
710
-
711
- <h3>Specifying type castings</h3>
712
-
713
- <p>Type castings can be specified using two forms: Either as a hash or as an array.
714
- While using an array only allows you to specify the supported source types to be
715
- casted, using a hash allows you to specify custom casting logic as blocks.</p>
716
-
717
- <p>For hashes, the key must be a class and the value must be either <code>:default</code> for
718
- using a built-in caster or a callable object (proc or lambda) that receives the
719
- value and is supposed to cast it. If the value can&#39;t be casted, the proc must
720
- fail with an exception. The exception message will then be contained in the
721
- collected validation errors.</p>
722
-
723
- <p>Example:</p>
724
-
725
- <pre class="code ruby"><code class="ruby">Schema.new do
726
- # Pass array to `cast`. This enables casting from String or Float to Integer
727
- # using the built-in casters.
728
- req :id_1, :integer, cast: [String, Float]
729
-
730
- # Pass hash to `cast`. This enables casting from Float to Integer using the
731
- # built-in caster and from String to Integer using a custom callback.
732
- req :id_2, :integer, cast: { Float =&gt; :default, String =&gt; proc { |s| Integer(s) }
733
- end
734
- </code></pre>
735
-
736
- <h3>Built-in casters</h3>
737
-
738
- <p>Schemacop comes with the following casters:</p>
739
-
740
- <ul>
741
- <li><code>String</code> to <code>Integer</code> and <code>Float</code></li>
742
- <li><code>Float</code> to <code>Integer</code></li>
743
- <li><code>Integer</code> to <code>Float</code></li>
744
- </ul>
745
-
746
- <p>Note that all built-in casters are precise, so the string <code>foo</code> will fail with
747
- an error if casted to an Integer. When casting float values and strings
748
- containing float values to integers, the decimal places will be discarded
749
- however.</p>
750
-
751
- <h3>Execution order</h3>
752
-
753
- <p>The casting is done <em>before</em> the options <code>if</code> and <code>check</code> are evaluated.
754
- Example:</p>
755
-
756
- <pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_s'>s</span> <span class='op'>=</span> <span class='const'>Schema</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span> <span class='kw'>do</span>
757
- <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:integer</span><span class='comma'>,</span> <span class='label'>if:</span> <span class='id identifier rubyid_proc'>proc</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_i'>i</span><span class='op'>|</span> <span class='id identifier rubyid_i'>i</span> <span class='op'>==</span> <span class='int'>42</span> <span class='rbrace'>}</span> <span class='comment'># 1
758
- </span> <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:integer</span><span class='comma'>,</span> <span class='label'>check:</span> <span class='id identifier rubyid_proc'>proc</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_i'>i</span><span class='op'>|</span> <span class='id identifier rubyid_i'>i</span> <span class='op'>&lt;</span> <span class='int'>3</span> <span class='rbrace'>}</span> <span class='comment'># 2
759
- </span> <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:string</span>
760
- <span class='kw'>end</span>
761
-
762
- <span class='id identifier rubyid_s'>s</span><span class='period'>.</span><span class='id identifier rubyid_validate!'>validate!</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>42</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span> <span class='comment'># 1 will match
763
- </span><span class='id identifier rubyid_s'>s</span><span class='period'>.</span><span class='id identifier rubyid_validate!'>validate!</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>2</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span> <span class='comment'># 2 will match
764
- </span><span class='id identifier rubyid_s'>s</span><span class='period'>.</span><span class='id identifier rubyid_validate!'>validate!</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>234</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span> <span class='comment'># 3 will match
765
- </span><span class='id identifier rubyid_s'>s</span><span class='period'>.</span><span class='id identifier rubyid_validate!'>validate!</span><span class='lparen'>(</span><span class='int'>5</span><span class='rparen'>)</span> <span class='comment'># Will fail, as nothing matches
766
- </span></code></pre>
767
-
768
- <h3>Caveats</h3>
769
-
770
- <p>Casting only works with type definitions that only include one type. For
771
- instance, the <code>Numeric</code> validator includes both <code>Integer</code> and <code>Float</code>, which
772
- would made it unclear what to cast a string into:</p>
773
-
774
- <pre class="code ruby"><code class="ruby"><span class='comment'># This does not work, as it is unclear whether to cast the String into an
775
- </span><span class='comment'># Integer or a Float.
776
- </span><span class='id identifier rubyid_type'>type</span> <span class='symbol'>:number</span><span class='comma'>,</span> <span class='label'>cast:</span> <span class='lbracket'>[</span><span class='const'>String</span><span class='rbracket'>]</span>
777
- </code></pre>
778
-
779
- <p>The same also applies to booleans, as they compound both <code>TrueClass</code> and
780
- <code>FalseClass</code>. This may be tackled in future releases.</p>
781
-
782
- <h2>Exceptions</h2>
783
-
784
- <p>Schemacop will throw one of the following checked exceptions:</p>
785
-
786
- <ul>
787
- <li><span class='object_link'><a href="Schemacop/Exceptions/InvalidSchemaError.html" title="Schemacop::Exceptions::InvalidSchemaError (class)">Schemacop::Exceptions::InvalidSchemaError</a></span></li>
788
- </ul>
789
-
790
- <p>This exception is thrown when the given schema definition format is invalid.</p>
791
-
792
- <ul>
793
- <li><span class='object_link'><a href="Schemacop/Exceptions/ValidationError.html" title="Schemacop::Exceptions::ValidationError (class)">Schemacop::Exceptions::ValidationError</a></span></li>
794
- </ul>
795
-
796
- <p>This exception is thrown when the given data does not comply with the given
797
- schema definition.</p>
798
-
799
- <h2>Known limitations</h2>
800
-
801
- <ul>
802
- <li><p>Schemacop does not yet allow cyclic structures with infinite depth.</p></li>
803
- <li><p>Schemacop is not made for validating complex causalities (i.e. field <code>a</code>
804
- needs to be given only if field <code>b</code> is present).</p></li>
805
- <li><p>Schemacop does not yet support string regex matching.</p></li>
806
- </ul>
807
-
808
- <h2>Development</h2>
809
-
810
- <p>To run tests:</p>
811
-
812
- <ul>
813
- <li><p>Check out the source</p></li>
814
- <li><p>Run <code>bundle install</code></p></li>
815
- <li><p>Run <code>bundle exec rake test</code> to run all tests</p></li>
816
- <li><p>Run <code>bundle exec rake test TEST=test/unit/some/file.rb</code> to run a single test
817
- file</p></li>
818
- </ul>
819
-
820
- <h2>Copyright</h2>
821
-
822
- <p>Copyright (c) 2020 Sitrox. See <code>LICENSE</code> for further details.</p>
823
- </div></div>
824
-
825
- <div id="footer">
826
- Generated on Thu Jul 2 11:30:33 2020 by
827
- <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
828
- 0.9.20 (ruby-2.6.2).
829
- </div>
830
-
831
- </div>
832
- </body>
833
- </html>