schemacop 2.3.2 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -0
- data/README.md +190 -2
- data/RUBY_VERSION +1 -1
- data/Rakefile +6 -5
- data/VERSION +1 -1
- data/doc/Schemacop.html +30 -3
- data/doc/Schemacop/ArrayValidator.html +2 -2
- data/doc/Schemacop/BooleanValidator.html +1 -1
- data/doc/Schemacop/Caster.html +379 -0
- data/doc/Schemacop/Collector.html +178 -102
- data/doc/Schemacop/Exceptions.html +1 -1
- data/doc/Schemacop/Exceptions/InvalidSchemaError.html +1 -1
- data/doc/Schemacop/Exceptions/ValidationError.html +1 -1
- data/doc/Schemacop/FieldNode.html +17 -5
- data/doc/Schemacop/FloatValidator.html +1 -1
- data/doc/Schemacop/HashValidator.html +1 -1
- data/doc/Schemacop/IntegerValidator.html +1 -1
- data/doc/Schemacop/NilValidator.html +1 -1
- data/doc/Schemacop/Node.html +95 -83
- data/doc/Schemacop/NodeResolver.html +26 -10
- data/doc/Schemacop/NodeSupportingField.html +1 -1
- data/doc/Schemacop/NodeSupportingType.html +2 -4
- data/doc/Schemacop/NodeWithBlock.html +1 -1
- data/doc/Schemacop/NumberValidator.html +1 -1
- data/doc/Schemacop/ObjectValidator.html +1 -1
- data/doc/Schemacop/RootNode.html +1 -1
- data/doc/Schemacop/Schema.html +3 -3
- data/doc/Schemacop/StringValidator.html +1 -1
- data/doc/Schemacop/SymbolValidator.html +1 -1
- data/doc/ScopedEnv.html +1 -1
- data/doc/_index.html +8 -1
- data/doc/class_list.html +1 -1
- data/doc/file.README.html +184 -3
- data/doc/index.html +184 -3
- data/doc/method_list.html +93 -61
- data/doc/top-level-namespace.html +1 -1
- data/lib/schemacop.rb +14 -0
- data/lib/schemacop/caster.rb +38 -0
- data/lib/schemacop/collector.rb +34 -6
- data/lib/schemacop/field_node.rb +25 -3
- data/lib/schemacop/node.rb +10 -2
- data/lib/schemacop/node_resolver.rb +10 -2
- data/lib/schemacop/node_supporting_type.rb +21 -1
- data/lib/schemacop/schema.rb +2 -2
- data/lib/schemacop/validator/array_validator.rb +1 -1
- data/lib/schemacop/validator/float_validator.rb +1 -1
- data/lib/schemacop/validator/integer_validator.rb +1 -1
- data/schemacop.gemspec +14 -8
- data/test/casting_test.rb +90 -0
- data/test/custom_check_test.rb +14 -14
- data/test/custom_if_test.rb +12 -12
- data/test/defaults_test.rb +71 -0
- data/test/nil_dis_allow_test.rb +6 -6
- data/test/node_resolver_test.rb +26 -0
- data/test/short_forms_test.rb +73 -66
- data/test/test_helper.rb +7 -0
- data/test/types_test.rb +5 -5
- data/test/validator_array_test.rb +16 -16
- data/test/validator_boolean_test.rb +2 -2
- data/test/validator_float_test.rb +15 -15
- data/test/validator_hash_test.rb +5 -5
- data/test/validator_integer_test.rb +9 -9
- data/test/validator_nil_test.rb +1 -1
- data/test/validator_number_test.rb +19 -19
- data/test/validator_object_test.rb +18 -18
- data/test/validator_string_test.rb +12 -12
- data/test/validator_symbol_test.rb +2 -2
- metadata +42 -6
@@ -117,7 +117,7 @@
|
|
117
117
|
<li class="public ">
|
118
118
|
<span class="summary_signature">
|
119
119
|
|
120
|
-
<a href="#register-class_method" title="register (class method)">.<strong>register</strong>(node_class) ⇒ Object </a>
|
120
|
+
<a href="#register-class_method" title="register (class method)">.<strong>register</strong>(node_class, before: nil) ⇒ Object </a>
|
121
121
|
|
122
122
|
|
123
123
|
|
@@ -170,7 +170,7 @@
|
|
170
170
|
<div class="method_details first">
|
171
171
|
<h3 class="signature first" id="register-class_method">
|
172
172
|
|
173
|
-
.<strong>register</strong>(node_class) ⇒ <tt>Object</tt>
|
173
|
+
.<strong>register</strong>(node_class, before: nil) ⇒ <tt>Object</tt>
|
174
174
|
|
175
175
|
|
176
176
|
|
@@ -184,13 +184,29 @@
|
|
184
184
|
|
185
185
|
6
|
186
186
|
7
|
187
|
-
8
|
187
|
+
8
|
188
|
+
9
|
189
|
+
10
|
190
|
+
11
|
191
|
+
12
|
192
|
+
13
|
193
|
+
14
|
194
|
+
15
|
195
|
+
16</pre>
|
188
196
|
</td>
|
189
197
|
<td>
|
190
198
|
<pre class="code"><span class="info file"># File 'lib/schemacop/node_resolver.rb', line 6</span>
|
191
199
|
|
192
|
-
<span class='kw'>def</span> <span class='kw'>self</span><span class='period'>.</span><span class='id identifier rubyid_register'>register</span><span class='lparen'>(</span><span class='id identifier rubyid_node_class'>node_class</span><span class='rparen'>)</span>
|
193
|
-
<span class='kw'>
|
200
|
+
<span class='kw'>def</span> <span class='kw'>self</span><span class='period'>.</span><span class='id identifier rubyid_register'>register</span><span class='lparen'>(</span><span class='id identifier rubyid_node_class'>node_class</span><span class='comma'>,</span> <span class='label'>before:</span> <span class='kw'>nil</span><span class='rparen'>)</span>
|
201
|
+
<span class='kw'>if</span> <span class='id identifier rubyid_before'>before</span>
|
202
|
+
<span class='kw'>unless</span> <span class='lparen'>(</span><span class='id identifier rubyid_index'>index</span> <span class='op'>=</span> <span class='kw'>self</span><span class='period'>.</span><span class='id identifier rubyid_node_classes'>node_classes</span><span class='period'>.</span><span class='id identifier rubyid_find_index'>find_index</span><span class='lparen'>(</span><span class='id identifier rubyid_before'>before</span><span class='rparen'>)</span><span class='rparen'>)</span>
|
203
|
+
<span class='id identifier rubyid_fail'>fail</span> <span class='tstring'><span class='tstring_beg'>"</span><span class='tstring_content'>Cannot insert before class </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_before'>before</span><span class='embexpr_end'>}</span><span class='tstring_content'> which has not been registered yet.</span><span class='tstring_end'>"</span></span>
|
204
|
+
<span class='kw'>end</span>
|
205
|
+
|
206
|
+
<span class='kw'>self</span><span class='period'>.</span><span class='id identifier rubyid_node_classes'>node_classes</span><span class='period'>.</span><span class='id identifier rubyid_insert'>insert</span><span class='lparen'>(</span><span class='id identifier rubyid_index'>index</span><span class='comma'>,</span> <span class='id identifier rubyid_node_class'>node_class</span><span class='rparen'>)</span>
|
207
|
+
<span class='kw'>else</span>
|
208
|
+
<span class='kw'>self</span><span class='period'>.</span><span class='id identifier rubyid_node_classes'>node_classes</span> <span class='op'>+=</span> <span class='lbracket'>[</span><span class='id identifier rubyid_node_class'>node_class</span><span class='rbracket'>]</span>
|
209
|
+
<span class='kw'>end</span>
|
194
210
|
<span class='kw'>end</span></pre>
|
195
211
|
</td>
|
196
212
|
</tr>
|
@@ -212,12 +228,12 @@
|
|
212
228
|
<pre class="lines">
|
213
229
|
|
214
230
|
|
215
|
-
|
216
|
-
|
217
|
-
|
231
|
+
18
|
232
|
+
19
|
233
|
+
20</pre>
|
218
234
|
</td>
|
219
235
|
<td>
|
220
|
-
<pre class="code"><span class="info file"># File 'lib/schemacop/node_resolver.rb', line
|
236
|
+
<pre class="code"><span class="info file"># File 'lib/schemacop/node_resolver.rb', line 18</span>
|
221
237
|
|
222
238
|
<span class='kw'>def</span> <span class='kw'>self</span><span class='period'>.</span><span class='id identifier rubyid_resolve'>resolve</span><span class='lparen'>(</span><span class='id identifier rubyid_type'>type</span><span class='rparen'>)</span>
|
223
239
|
<span class='id identifier rubyid_node_classes'>node_classes</span><span class='period'>.</span><span class='id identifier rubyid_find'>find</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_c'>c</span><span class='op'>|</span> <span class='id identifier rubyid_c'>c</span><span class='period'>.</span><span class='id identifier rubyid_type_matches?'>type_matches?</span><span class='lparen'>(</span><span class='id identifier rubyid_type'>type</span><span class='rparen'>)</span> <span class='rbrace'>}</span>
|
@@ -232,7 +248,7 @@
|
|
232
248
|
</div>
|
233
249
|
|
234
250
|
<div id="footer">
|
235
|
-
Generated on
|
251
|
+
Generated on Mon Oct 28 16:21:59 2019 by
|
236
252
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
237
253
|
0.9.20 (ruby-2.6.2).
|
238
254
|
</div>
|
@@ -580,7 +580,7 @@
|
|
580
580
|
</div>
|
581
581
|
|
582
582
|
<div id="footer">
|
583
|
-
Generated on
|
583
|
+
Generated on Mon Oct 28 16:21:59 2019 by
|
584
584
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
585
585
|
0.9.20 (ruby-2.6.2).
|
586
586
|
</div>
|
@@ -583,15 +583,13 @@ as it formerly was the case in the constructor.</p>
|
|
583
583
|
94
|
584
584
|
95
|
585
585
|
96
|
586
|
-
97
|
587
|
-
98</pre>
|
586
|
+
97</pre>
|
588
587
|
</td>
|
589
588
|
<td>
|
590
589
|
<pre class="code"><span class="info file"># File 'lib/schemacop/node_supporting_type.rb', line 94</span>
|
591
590
|
|
592
591
|
<span class='kw'>def</span> <span class='id identifier rubyid_validate'>validate</span><span class='lparen'>(</span><span class='id identifier rubyid_data'>data</span><span class='comma'>,</span> <span class='id identifier rubyid_collector'>collector</span><span class='rparen'>)</span>
|
593
592
|
<span class='kw'>super</span>
|
594
|
-
|
595
593
|
<span class='id identifier rubyid_validate_types'>validate_types</span><span class='lparen'>(</span><span class='id identifier rubyid_data'>data</span><span class='comma'>,</span> <span class='id identifier rubyid_collector'>collector</span><span class='rparen'>)</span>
|
596
594
|
<span class='kw'>end</span></pre>
|
597
595
|
</td>
|
@@ -604,7 +602,7 @@ as it formerly was the case in the constructor.</p>
|
|
604
602
|
</div>
|
605
603
|
|
606
604
|
<div id="footer">
|
607
|
-
Generated on
|
605
|
+
Generated on Mon Oct 28 16:21:59 2019 by
|
608
606
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
609
607
|
0.9.20 (ruby-2.6.2).
|
610
608
|
</div>
|
@@ -279,7 +279,7 @@
|
|
279
279
|
</div>
|
280
280
|
|
281
281
|
<div id="footer">
|
282
|
-
Generated on
|
282
|
+
Generated on Mon Oct 28 16:21:59 2019 by
|
283
283
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
284
284
|
0.9.20 (ruby-2.6.2).
|
285
285
|
</div>
|
@@ -222,7 +222,7 @@
|
|
222
222
|
</div>
|
223
223
|
|
224
224
|
<div id="footer">
|
225
|
-
Generated on
|
225
|
+
Generated on Mon Oct 28 16:21:59 2019 by
|
226
226
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
227
227
|
0.9.20 (ruby-2.6.2).
|
228
228
|
</div>
|
@@ -288,7 +288,7 @@
|
|
288
288
|
</div>
|
289
289
|
|
290
290
|
<div id="footer">
|
291
|
-
Generated on
|
291
|
+
Generated on Mon Oct 28 16:21:59 2019 by
|
292
292
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
293
293
|
0.9.20 (ruby-2.6.2).
|
294
294
|
</div>
|
data/doc/Schemacop/RootNode.html
CHANGED
@@ -161,7 +161,7 @@
|
|
161
161
|
</div>
|
162
162
|
|
163
163
|
<div id="footer">
|
164
|
-
Generated on
|
164
|
+
Generated on Mon Oct 28 16:21:59 2019 by
|
165
165
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
166
166
|
0.9.20 (ruby-2.6.2).
|
167
167
|
</div>
|
data/doc/Schemacop/Schema.html
CHANGED
@@ -567,7 +567,7 @@ throughout the validation.</p>
|
|
567
567
|
<pre class="code"><span class="info file"># File 'lib/schemacop/schema.rb', line 39</span>
|
568
568
|
|
569
569
|
<span class='kw'>def</span> <span class='id identifier rubyid_validate'>validate</span><span class='lparen'>(</span><span class='id identifier rubyid_data'>data</span><span class='rparen'>)</span>
|
570
|
-
<span class='id identifier rubyid_collector'>collector</span> <span class='op'>=</span> <span class='const'><span class='object_link'><a href="Collector.html" title="Schemacop::Collector (class)">Collector</a></span></span><span class='period'>.</span><span class='id identifier rubyid_new'><span class='object_link'><a href="Collector.html#initialize-instance_method" title="Schemacop::Collector#initialize (method)">new</a></span></span>
|
570
|
+
<span class='id identifier rubyid_collector'>collector</span> <span class='op'>=</span> <span class='const'><span class='object_link'><a href="Collector.html" title="Schemacop::Collector (class)">Collector</a></span></span><span class='period'>.</span><span class='id identifier rubyid_new'><span class='object_link'><a href="Collector.html#initialize-instance_method" title="Schemacop::Collector#initialize (method)">new</a></span></span><span class='lparen'>(</span><span class='id identifier rubyid_data'>data</span><span class='period'>.</span><span class='id identifier rubyid_deep_dup'>deep_dup</span><span class='rparen'>)</span>
|
571
571
|
<span class='ivar'>@root</span><span class='period'>.</span><span class='id identifier rubyid_fields'>fields</span><span class='lbracket'>[</span><span class='symbol'>:root</span><span class='rbracket'>]</span><span class='period'>.</span><span class='id identifier rubyid_validate'>validate</span><span class='lparen'>(</span><span class='lbrace'>{</span> <span class='label'>root:</span> <span class='id identifier rubyid_data'>data</span> <span class='rbrace'>}</span><span class='comma'>,</span> <span class='id identifier rubyid_collector'>collector</span><span class='period'>.</span><span class='id identifier rubyid_ignore_next_segment'>ignore_next_segment</span><span class='rparen'>)</span>
|
572
572
|
<span class='kw'>return</span> <span class='id identifier rubyid_collector'>collector</span>
|
573
573
|
<span class='kw'>end</span></pre>
|
@@ -675,7 +675,7 @@ this exception is thrown.</p>
|
|
675
675
|
<span class='id identifier rubyid_fail'>fail</span> <span class='const'><span class='object_link'><a href="Exceptions.html" title="Schemacop::Exceptions (module)">Exceptions</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="Exceptions/ValidationError.html" title="Schemacop::Exceptions::ValidationError (class)">ValidationError</a></span></span><span class='comma'>,</span> <span class='id identifier rubyid_collector'>collector</span><span class='period'>.</span><span class='id identifier rubyid_exception_message'>exception_message</span>
|
676
676
|
<span class='kw'>end</span>
|
677
677
|
|
678
|
-
<span class='kw'>return</span> <span class='
|
678
|
+
<span class='kw'>return</span> <span class='id identifier rubyid_collector'>collector</span><span class='period'>.</span><span class='id identifier rubyid_data'>data</span>
|
679
679
|
<span class='kw'>end</span></pre>
|
680
680
|
</td>
|
681
681
|
</tr>
|
@@ -687,7 +687,7 @@ this exception is thrown.</p>
|
|
687
687
|
</div>
|
688
688
|
|
689
689
|
<div id="footer">
|
690
|
-
Generated on
|
690
|
+
Generated on Mon Oct 28 16:21:59 2019 by
|
691
691
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
692
692
|
0.9.20 (ruby-2.6.2).
|
693
693
|
</div>
|
@@ -285,7 +285,7 @@
|
|
285
285
|
</div>
|
286
286
|
|
287
287
|
<div id="footer">
|
288
|
-
Generated on
|
288
|
+
Generated on Mon Oct 28 16:21:59 2019 by
|
289
289
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
290
290
|
0.9.20 (ruby-2.6.2).
|
291
291
|
</div>
|
@@ -135,7 +135,7 @@
|
|
135
135
|
</div>
|
136
136
|
|
137
137
|
<div id="footer">
|
138
|
-
Generated on
|
138
|
+
Generated on Mon Oct 28 16:22:00 2019 by
|
139
139
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
140
140
|
0.9.20 (ruby-2.6.2).
|
141
141
|
</div>
|
data/doc/ScopedEnv.html
CHANGED
@@ -341,7 +341,7 @@
|
|
341
341
|
</div>
|
342
342
|
|
343
343
|
<div id="footer">
|
344
|
-
Generated on
|
344
|
+
Generated on Mon Oct 28 16:21:59 2019 by
|
345
345
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
346
346
|
0.9.20 (ruby-2.6.2).
|
347
347
|
</div>
|
data/doc/_index.html
CHANGED
@@ -110,6 +110,13 @@
|
|
110
110
|
<li class="letter">C</li>
|
111
111
|
<ul>
|
112
112
|
|
113
|
+
<li>
|
114
|
+
<span class='object_link'><a href="Schemacop/Caster.html" title="Schemacop::Caster (class)">Caster</a></span>
|
115
|
+
|
116
|
+
<small>(Schemacop)</small>
|
117
|
+
|
118
|
+
</li>
|
119
|
+
|
113
120
|
<li>
|
114
121
|
<span class='object_link'><a href="Schemacop/Collector.html" title="Schemacop::Collector (class)">Collector</a></span>
|
115
122
|
|
@@ -347,7 +354,7 @@
|
|
347
354
|
</div>
|
348
355
|
|
349
356
|
<div id="footer">
|
350
|
-
Generated on
|
357
|
+
Generated on Mon Oct 28 16:21:59 2019 by
|
351
358
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
352
359
|
0.9.20 (ruby-2.6.2).
|
353
360
|
</div>
|
data/doc/class_list.html
CHANGED
@@ -43,7 +43,7 @@
|
|
43
43
|
|
44
44
|
<ul id="full_list" class="class">
|
45
45
|
<li id="object_" class="odd"><div class="item" style="padding-left:30px"><span class='object_link'><a href="top-level-namespace.html" title="Top Level Namespace (root)">Top Level Namespace</a></span></div></li>
|
46
|
-
<li id='object_Schemacop' class='even'><div class='item' style='padding-left:30px'><a class='toggle'></a> <span class='object_link'><a href="Schemacop.html" title="Schemacop (module)">Schemacop</a></span><small class='search_info'>Top Level Namespace</small></div><ul><li id='object_Schemacop::ArrayValidator' class='collapsed odd'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Schemacop/ArrayValidator.html" title="Schemacop::ArrayValidator (class)">ArrayValidator</a></span> < NodeSupportingType<small class='search_info'>Schemacop</small></div></li><li id='object_Schemacop::BooleanValidator' class='collapsed even'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Schemacop/BooleanValidator.html" title="Schemacop::BooleanValidator (class)">BooleanValidator</a></span> < Node<small class='search_info'>Schemacop</small></div></li><li id='object_Schemacop::
|
46
|
+
<li id='object_Schemacop' class='even'><div class='item' style='padding-left:30px'><a class='toggle'></a> <span class='object_link'><a href="Schemacop.html" title="Schemacop (module)">Schemacop</a></span><small class='search_info'>Top Level Namespace</small></div><ul><li id='object_Schemacop::ArrayValidator' class='collapsed odd'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Schemacop/ArrayValidator.html" title="Schemacop::ArrayValidator (class)">ArrayValidator</a></span> < NodeSupportingType<small class='search_info'>Schemacop</small></div></li><li id='object_Schemacop::BooleanValidator' class='collapsed even'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Schemacop/BooleanValidator.html" title="Schemacop::BooleanValidator (class)">BooleanValidator</a></span> < Node<small class='search_info'>Schemacop</small></div></li><li id='object_Schemacop::Caster' class='collapsed odd'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Schemacop/Caster.html" title="Schemacop::Caster (class)">Caster</a></span> < Object<small class='search_info'>Schemacop</small></div></li><li id='object_Schemacop::Collector' class='collapsed even'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Schemacop/Collector.html" title="Schemacop::Collector (class)">Collector</a></span> < Object<small class='search_info'>Schemacop</small></div></li><li id='object_Schemacop::Exceptions' class='collapsed odd'><div class='item' style='padding-left:45px'><a class='toggle'></a> <span class='object_link'><a href="Schemacop/Exceptions.html" title="Schemacop::Exceptions (module)">Exceptions</a></span><small class='search_info'>Schemacop</small></div><ul><li id='object_Schemacop::Exceptions::InvalidSchemaError' class='collapsed'><div class='item' style='padding-left:60px'><span class='object_link'><a href="Schemacop/Exceptions/InvalidSchemaError.html" title="Schemacop::Exceptions::InvalidSchemaError (class)">InvalidSchemaError</a></span> < RuntimeError<small class='search_info'>Schemacop::Exceptions</small></div></li><li id='object_Schemacop::Exceptions::ValidationError' class='collapsed'><div class='item' style='padding-left:60px'><span class='object_link'><a href="Schemacop/Exceptions/ValidationError.html" title="Schemacop::Exceptions::ValidationError (class)">ValidationError</a></span> < RuntimeError<small class='search_info'>Schemacop::Exceptions</small></div></li></ul></li><li id='object_Schemacop::FieldNode' class='collapsed even'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Schemacop/FieldNode.html" title="Schemacop::FieldNode (class)">FieldNode</a></span> < NodeSupportingType<small class='search_info'>Schemacop</small></div></li><li id='object_Schemacop::FloatValidator' class='collapsed odd'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Schemacop/FloatValidator.html" title="Schemacop::FloatValidator (class)">FloatValidator</a></span> < NumberValidator<small class='search_info'>Schemacop</small></div></li><li id='object_Schemacop::HashValidator' class='collapsed even'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Schemacop/HashValidator.html" title="Schemacop::HashValidator (class)">HashValidator</a></span> < NodeSupportingField<small class='search_info'>Schemacop</small></div></li><li id='object_Schemacop::IntegerValidator' class='collapsed odd'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Schemacop/IntegerValidator.html" title="Schemacop::IntegerValidator (class)">IntegerValidator</a></span> < NumberValidator<small class='search_info'>Schemacop</small></div></li><li id='object_Schemacop::NilValidator' class='collapsed even'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Schemacop/NilValidator.html" title="Schemacop::NilValidator (class)">NilValidator</a></span> < Node<small class='search_info'>Schemacop</small></div></li><li id='object_Schemacop::Node' class='collapsed odd'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Schemacop/Node.html" title="Schemacop::Node (class)">Node</a></span> < Object<small class='search_info'>Schemacop</small></div></li><li id='object_Schemacop::NodeResolver' class='collapsed even'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Schemacop/NodeResolver.html" title="Schemacop::NodeResolver (class)">NodeResolver</a></span> < Object<small class='search_info'>Schemacop</small></div></li><li id='object_Schemacop::NodeSupportingField' class='collapsed odd'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Schemacop/NodeSupportingField.html" title="Schemacop::NodeSupportingField (class)">NodeSupportingField</a></span> < NodeWithBlock<small class='search_info'>Schemacop</small></div></li><li id='object_Schemacop::NodeSupportingType' class='collapsed even'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Schemacop/NodeSupportingType.html" title="Schemacop::NodeSupportingType (class)">NodeSupportingType</a></span> < NodeWithBlock<small class='search_info'>Schemacop</small></div></li><li id='object_Schemacop::NodeWithBlock' class='collapsed odd'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Schemacop/NodeWithBlock.html" title="Schemacop::NodeWithBlock (class)">NodeWithBlock</a></span> < Node<small class='search_info'>Schemacop</small></div></li><li id='object_Schemacop::NumberValidator' class='collapsed even'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Schemacop/NumberValidator.html" title="Schemacop::NumberValidator (class)">NumberValidator</a></span> < Node<small class='search_info'>Schemacop</small></div></li><li id='object_Schemacop::ObjectValidator' class='collapsed odd'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Schemacop/ObjectValidator.html" title="Schemacop::ObjectValidator (class)">ObjectValidator</a></span> < Node<small class='search_info'>Schemacop</small></div></li><li id='object_Schemacop::RootNode' class='collapsed even'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Schemacop/RootNode.html" title="Schemacop::RootNode (class)">RootNode</a></span> < NodeSupportingType<small class='search_info'>Schemacop</small></div></li><li id='object_Schemacop::Schema' class='collapsed odd'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Schemacop/Schema.html" title="Schemacop::Schema (class)">Schema</a></span> < Object<small class='search_info'>Schemacop</small></div></li><li id='object_Schemacop::StringValidator' class='collapsed even'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Schemacop/StringValidator.html" title="Schemacop::StringValidator (class)">StringValidator</a></span> < Node<small class='search_info'>Schemacop</small></div></li><li id='object_Schemacop::SymbolValidator' class='collapsed odd'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Schemacop/SymbolValidator.html" title="Schemacop::SymbolValidator (class)">SymbolValidator</a></span> < Node<small class='search_info'>Schemacop</small></div></li></ul></li><li id='object_ScopedEnv' class='even'><div class='item' style='padding-left:30px'><span class='object_link'><a href="ScopedEnv.html" title="ScopedEnv (class)">ScopedEnv</a></span> < Object<small class='search_info'>Top Level Namespace</small></div></li>
|
47
47
|
|
48
48
|
</ul>
|
49
49
|
</div>
|
data/doc/file.README.html
CHANGED
@@ -177,12 +177,38 @@ FalseClass).</p>
|
|
177
177
|
<h3><code>validate</code> vs <code>validate!</code> vs <code>valid?</code></h3>
|
178
178
|
|
179
179
|
<p>The method <code>validate</code> will return a <code>Collector</code> object that contains all
|
180
|
-
validation errors (if any)
|
181
|
-
and
|
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>
|
182
185
|
|
183
186
|
<p>For simply querying the validity of some data, use the methods <code>valid?</code> or
|
184
187
|
<code>invalid?</code>.</p>
|
185
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'># => { 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'># => { 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'>'</span><span class='tstring_content'>invalid</span><span class='tstring_end'>'</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'># => 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'># => Validation error
|
210
|
+
</span></code></pre>
|
211
|
+
|
186
212
|
<h2>Schemacop's DSL</h2>
|
187
213
|
|
188
214
|
<p>In this section, we will ignore <a href="#short-forms">short forms</a> and explicitly
|
@@ -540,6 +566,10 @@ write Field Lines in the schema instantiation:</p>
|
|
540
566
|
<span class='kw'>end</span>
|
541
567
|
</code></pre>
|
542
568
|
|
569
|
+
<p>Note that this does not allow you to specify any options for the hash itself.
|
570
|
+
You still need to specify <code>:hash</code> as a type if you want to pass any options to
|
571
|
+
the hash (i.e. a <code>default</code>).</p>
|
572
|
+
|
543
573
|
<h3>Shortform for subtypes</h3>
|
544
574
|
|
545
575
|
<p>In case of nested arrays, you can group all Type Lines to a single one.</p>
|
@@ -595,6 +625,145 @@ of type Array with children of type Array with children of type Hash in which at
|
|
595
625
|
least one of the Symbol keys <code>:food</code> and <code>:drink</code> (with any non-nil value type)
|
596
626
|
is present.</p>
|
597
627
|
|
628
|
+
<h2>Defaults</h2>
|
629
|
+
|
630
|
+
<p>Starting from version 2.4.0, Schemacop allows you to define default values at
|
631
|
+
any point in your schema. If the validated data contains a nil value, it will be
|
632
|
+
substituted by the given default value.</p>
|
633
|
+
|
634
|
+
<p>Note that Schemacop never modifies the data you pass to it. If you want to
|
635
|
+
benefit from Schemacop-applied defaults, you need to access the cloned, modified
|
636
|
+
data returned by <code>validate</code> or <code>validate!</code>.</p>
|
637
|
+
|
638
|
+
<p>Applying defaults is done before validating the substructure and before any type
|
639
|
+
casting. The provided default will be validated same as user-supplied data, so
|
640
|
+
if your given default does not validate properly, a validation error is thrown.
|
641
|
+
Make sure your default values always match the underlying schema.</p>
|
642
|
+
|
643
|
+
<p>Defaults can be specified at any point:</p>
|
644
|
+
|
645
|
+
<pre class="code ruby"><code class="ruby"><span class='comment'># Basic usage
|
646
|
+
</span><span class='const'>Schema</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span> <span class='kw'>do</span>
|
647
|
+
<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'>'</span><span class='tstring_content'>Hello World</span><span class='tstring_end'>'</span></span>
|
648
|
+
<span class='kw'>end</span>
|
649
|
+
|
650
|
+
<span class='comment'># The default given for the first type will match
|
651
|
+
</span><span class='const'>Schema</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span> <span class='kw'>do</span>
|
652
|
+
<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'>'</span><span class='tstring_content'>Hello World</span><span class='tstring_end'>'</span></span> <span class='comment'># This will always be applied of no value is supplied
|
653
|
+
</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>
|
654
|
+
<span class='kw'>end</span>
|
655
|
+
|
656
|
+
<span class='comment'># You can also pass entire hashes or arrays to your defaults
|
657
|
+
</span><span class='const'>Schema</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span> <span class='kw'>do</span>
|
658
|
+
<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>
|
659
|
+
<span class='id identifier rubyid_req'>req</span> <span class='symbol'>:foo</span><span class='comma'>,</span> <span class='symbol'>:symbol</span>
|
660
|
+
<span class='kw'>end</span>
|
661
|
+
<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>
|
662
|
+
<span class='kw'>end</span>
|
663
|
+
|
664
|
+
<span class='comment'># Defaults must match the given schema. The following will fail.
|
665
|
+
</span><span class='const'>Schema</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span> <span class='kw'>do</span>
|
666
|
+
<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>
|
667
|
+
<span class='id identifier rubyid_req'>req</span> <span class='symbol'>:foo</span>
|
668
|
+
<span class='kw'>end</span>
|
669
|
+
<span class='kw'>end</span>
|
670
|
+
</code></pre>
|
671
|
+
|
672
|
+
<h3>Required data points</h3>
|
673
|
+
|
674
|
+
<p>Note that any <em>required</em> validation is done before applying the defaults. If you
|
675
|
+
specify a <code>req</code> field, it must always be given, no matter if you have specified
|
676
|
+
a default or not. Therefore, specifying <code>req</code> fields do not make sense in
|
677
|
+
conjunction with defaults, as the default is always ignored.</p>
|
678
|
+
|
679
|
+
<h2>Type casting</h2>
|
680
|
+
|
681
|
+
<p>Starting from version 2.4.0, Schemacop allows you to specify type castings that
|
682
|
+
can alter the validated data. Consider the following:</p>
|
683
|
+
|
684
|
+
<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>
|
685
|
+
<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>
|
686
|
+
<span class='kw'>end</span>
|
687
|
+
|
688
|
+
<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'>'</span><span class='tstring_content'>42</span><span class='tstring_end'>'</span></span><span class='rparen'>)</span>
|
689
|
+
<span class='id identifier rubyid_data'>data</span> <span class='comment'># => { id: 42 }
|
690
|
+
</span></code></pre>
|
691
|
+
|
692
|
+
<p>Note that Schemacop never modifies the data you pass to it. If you want to
|
693
|
+
benefit from Schemacop-applied castings, you need to access the cloned, modified
|
694
|
+
data returned by <code>validate</code> or <code>validate!</code>.</p>
|
695
|
+
|
696
|
+
<h3>Specifying type castings</h3>
|
697
|
+
|
698
|
+
<p>Type castings can be specified using two forms: Either as a hash or as an array.
|
699
|
+
While using an array only allows you to specify the supported source types to be
|
700
|
+
casted, using a hash allows you to specify custom casting logic as blocks.</p>
|
701
|
+
|
702
|
+
<p>For hashes, the key must be a class and the value must be either <code>:default</code> for
|
703
|
+
using a built-in caster or a callable object (proc or lambda) that receives the
|
704
|
+
value and is supposed to cast it. If the value can't be casted, the proc must
|
705
|
+
fail with an exception. The exception message will then be contained in the
|
706
|
+
collected validation errors.</p>
|
707
|
+
|
708
|
+
<p>Example:</p>
|
709
|
+
|
710
|
+
<pre class="code ruby"><code class="ruby">Schema.new do
|
711
|
+
# Pass array to `cast`. This enables casting from String or Float to Integer
|
712
|
+
# using the built-in casters.
|
713
|
+
req: id_1, :integer, cast: [String, Float]
|
714
|
+
|
715
|
+
# Pass hash to `cast`. This enables casting from Float to Integer using the
|
716
|
+
# built-in caster and from String to Integer using a custom callback.
|
717
|
+
req :id_2, :integer, cast: { Float => :default, String => proc { |s| Integer(s) }
|
718
|
+
end
|
719
|
+
</code></pre>
|
720
|
+
|
721
|
+
<h3>Built-in casters</h3>
|
722
|
+
|
723
|
+
<p>Schemacop comes with the following casters:</p>
|
724
|
+
|
725
|
+
<ul>
|
726
|
+
<li><code>String</code> to <code>Integer</code> and <code>Float</code></li>
|
727
|
+
<li><code>Float</code> to <code>Integer</code></li>
|
728
|
+
<li><code>Integer</code> to <code>Float</code></li>
|
729
|
+
</ul>
|
730
|
+
|
731
|
+
<p>Note that all built-in casters are precise, so the string <code>foo</code> will fail with
|
732
|
+
an error if casted to an Integer. When casting float values and strings
|
733
|
+
containing float values to integers, the decimal places will be discarded
|
734
|
+
however.</p>
|
735
|
+
|
736
|
+
<h3>Execution order</h3>
|
737
|
+
|
738
|
+
<p>The casting is done <em>before</em> the options <code>if</code> and <code>check</code> are evaluated.
|
739
|
+
Example:</p>
|
740
|
+
|
741
|
+
<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>
|
742
|
+
<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
|
743
|
+
</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'><</span> <span class='int'>3</span> <span class='rbrace'>}</span> <span class='comment'># 2
|
744
|
+
</span> <span class='id identifier rubyid_type'>type</span> <span class='symbol'>:string</span>
|
745
|
+
<span class='kw'>end</span>
|
746
|
+
|
747
|
+
<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'>'</span><span class='tstring_content'>42</span><span class='tstring_end'>'</span></span><span class='rparen'>)</span> <span class='comment'># 1 will match
|
748
|
+
</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'>'</span><span class='tstring_content'>2</span><span class='tstring_end'>'</span></span><span class='rparen'>)</span> <span class='comment'># 2 will match
|
749
|
+
</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'>'</span><span class='tstring_content'>234</span><span class='tstring_end'>'</span></span><span class='rparen'>)</span> <span class='comment'># 3 will match
|
750
|
+
</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
|
751
|
+
</span></code></pre>
|
752
|
+
|
753
|
+
<h3>Caveats</h3>
|
754
|
+
|
755
|
+
<p>Casting only works with type definitions that only include one type. For
|
756
|
+
instance, the <code>Numeric</code> validator includes both <code>Integer</code> and <code>Float</code>, which
|
757
|
+
would made it unclear what to cast a string into:</p>
|
758
|
+
|
759
|
+
<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
|
760
|
+
</span><span class='comment'># Integer or a Float.
|
761
|
+
</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>
|
762
|
+
</code></pre>
|
763
|
+
|
764
|
+
<p>The same also applies to booleans, as they compound both <code>TrueClass</code> and
|
765
|
+
<code>FalseClass</code>. This may be tackled in future releases.</p>
|
766
|
+
|
598
767
|
<h2>Exceptions</h2>
|
599
768
|
|
600
769
|
<p>Schemacop will throw one of the following checked exceptions:</p>
|
@@ -623,6 +792,18 @@ needs to be given only if field <code>b</code> is present).</p></li>
|
|
623
792
|
<li><p>Schemacop does not yet support string regex matching.</p></li>
|
624
793
|
</ul>
|
625
794
|
|
795
|
+
<h2>Development</h2>
|
796
|
+
|
797
|
+
<p>To run tests:</p>
|
798
|
+
|
799
|
+
<ul>
|
800
|
+
<li><p>Check out the source</p></li>
|
801
|
+
<li><p>Run <code>bundle install</code></p></li>
|
802
|
+
<li><p>Run <code>bundle exec rake test</code> to run all tests</p></li>
|
803
|
+
<li><p>Run <code>bundle exec rake test TEST=test/unit/some/file.rb</code> to run a single test
|
804
|
+
file</p></li>
|
805
|
+
</ul>
|
806
|
+
|
626
807
|
<h2>Contributors</h2>
|
627
808
|
|
628
809
|
<p>Thanks to <a href="https://github.com/bbatsov/rubocop">Rubocop</a> for great inspiration
|
@@ -635,7 +816,7 @@ to <a href="http://www.subgit.com/">SubGit</a> for their great open source licen
|
|
635
816
|
</div></div>
|
636
817
|
|
637
818
|
<div id="footer">
|
638
|
-
Generated on
|
819
|
+
Generated on Mon Oct 28 16:21:59 2019 by
|
639
820
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
640
821
|
0.9.20 (ruby-2.6.2).
|
641
822
|
</div>
|