schemacop 2.1.0 → 2.4.0
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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +58 -0
- data/LICENSE +1 -1
- data/README.md +250 -16
- data/RUBY_VERSION +1 -1
- data/Rakefile +6 -1
- data/VERSION +1 -1
- data/doc/Schemacop.html +32 -5
- data/doc/Schemacop/ArrayValidator.html +4 -4
- data/doc/Schemacop/BooleanValidator.html +4 -4
- data/doc/Schemacop/Caster.html +379 -0
- data/doc/Schemacop/Collector.html +298 -46
- data/doc/Schemacop/Exceptions.html +3 -3
- data/doc/Schemacop/Exceptions/InvalidSchemaError.html +3 -3
- data/doc/Schemacop/Exceptions/ValidationError.html +3 -3
- data/doc/Schemacop/FieldNode.html +19 -7
- data/doc/Schemacop/FloatValidator.html +4 -4
- data/doc/Schemacop/HashValidator.html +33 -7
- data/doc/Schemacop/IntegerValidator.html +4 -4
- data/doc/Schemacop/NilValidator.html +4 -4
- data/doc/Schemacop/Node.html +97 -85
- data/doc/Schemacop/NodeResolver.html +28 -12
- data/doc/Schemacop/NodeSupportingField.html +4 -4
- data/doc/Schemacop/NodeSupportingType.html +5 -7
- data/doc/Schemacop/NodeWithBlock.html +4 -4
- data/doc/Schemacop/NumberValidator.html +4 -4
- data/doc/Schemacop/ObjectValidator.html +20 -10
- data/doc/Schemacop/RootNode.html +4 -4
- data/doc/Schemacop/Schema.html +6 -6
- data/doc/Schemacop/StringValidator.html +3 -3
- data/doc/Schemacop/SymbolValidator.html +4 -4
- data/doc/ScopedEnv.html +3 -3
- data/doc/_index.html +11 -4
- data/doc/class_list.html +1 -1
- data/doc/css/style.css +10 -6
- data/doc/file.README.html +255 -29
- data/doc/frames.html +1 -1
- data/doc/index.html +255 -29
- data/doc/js/app.js +55 -0
- data/doc/method_list.html +99 -51
- data/doc/top-level-namespace.html +3 -3
- data/lib/schemacop.rb +15 -0
- data/lib/schemacop/caster.rb +38 -0
- data/lib/schemacop/collector.rb +53 -6
- data/lib/schemacop/field_node.rb +25 -3
- data/lib/schemacop/node.rb +16 -4
- data/lib/schemacop/node_resolver.rb +10 -2
- data/lib/schemacop/node_supporting_field.rb +0 -2
- data/lib/schemacop/node_supporting_type.rb +21 -1
- data/lib/schemacop/schema.rb +3 -3
- data/lib/schemacop/validator/array_validator.rb +1 -1
- data/lib/schemacop/validator/float_validator.rb +1 -1
- data/lib/schemacop/validator/hash_validator.rb +15 -2
- data/lib/schemacop/validator/integer_validator.rb +1 -1
- data/lib/schemacop/validator/object_validator.rb +7 -1
- data/schemacop.gemspec +15 -9
- data/test/casting_test.rb +90 -0
- data/test/collector_test.rb +45 -0
- data/test/custom_check_test.rb +20 -13
- 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 +86 -64
- 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 +33 -15
- data/test/validator_string_test.rb +12 -12
- data/test/validator_symbol_test.rb +2 -2
- metadata +43 -6
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/css/style.css
CHANGED
@@ -245,6 +245,7 @@ ul.toplevel { list-style: none; padding-left: 0; font-size: 1.1em; }
|
|
245
245
|
|
246
246
|
dl.constants { margin-left: 10px; }
|
247
247
|
dl.constants dt { font-weight: bold; font-size: 1.1em; margin-bottom: 5px; }
|
248
|
+
dl.constants.compact dt { display: inline-block; font-weight: normal }
|
248
249
|
dl.constants dd { width: 75%; white-space: pre; font-family: monospace; margin-bottom: 18px; }
|
249
250
|
dl.constants .docstring .note:first-child { margin-top: 5px; }
|
250
251
|
|
@@ -326,13 +327,9 @@ ul.summary a, ul.summary a:visited {
|
|
326
327
|
text-decoration: none; font-size: 1.1em;
|
327
328
|
}
|
328
329
|
ul.summary li { margin-bottom: 5px; }
|
329
|
-
.
|
330
|
-
padding: 4px 8px;
|
331
|
-
background: #f8f8f8;
|
332
|
-
border: 1px solid #f0f0f0;
|
333
|
-
border-radius: 5px;
|
334
|
-
}
|
330
|
+
.summary_signature { padding: 4px 8px; background: #f8f8f8; border: 1px solid #f0f0f0; border-radius: 5px; }
|
335
331
|
.summary_signature:hover { background: #CFEBFF; border-color: #A4CCDA; cursor: pointer; }
|
332
|
+
.summary_signature.deprecated { background: #ffe5e5; border-color: #e9dada; }
|
336
333
|
ul.summary.compact li { display: inline-block; margin: 0px 5px 0px 0px; line-height: 2.6em;}
|
337
334
|
ul.summary.compact .summary_signature { padding: 5px 7px; padding-right: 4px; }
|
338
335
|
#content .summary_signature:hover a,
|
@@ -484,6 +481,13 @@ pre.code .rubyid_backref,
|
|
484
481
|
pre.code .rubyid_nth_ref { color: #6D79DE; }
|
485
482
|
pre.code .regexp, .dregexp { color: #036A07; }
|
486
483
|
pre.code a { border-bottom: 1px dotted #bbf; }
|
484
|
+
/* inline code */
|
485
|
+
*:not(pre) > code {
|
486
|
+
padding: 1px 3px 1px 3px;
|
487
|
+
border: 1px solid #E1E1E8;
|
488
|
+
background: #F7F7F9;
|
489
|
+
border-radius: 4px;
|
490
|
+
}
|
487
491
|
|
488
492
|
/* Color fix for links */
|
489
493
|
#content .summary_desc pre.code .id > .object_link a, /* identifier */
|
data/doc/file.README.html
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
<title>
|
7
7
|
File: README
|
8
8
|
|
9
|
-
— Documentation by YARD 0.9.
|
9
|
+
— Documentation by YARD 0.9.20
|
10
10
|
|
11
11
|
</title>
|
12
12
|
|
@@ -132,7 +132,7 @@ around at runtime. Those two steps look as follows:</p>
|
|
132
132
|
|
133
133
|
<p>At runtime:</p>
|
134
134
|
|
135
|
-
<pre class="code ruby"><code class="ruby"><span class='id identifier
|
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
136
|
<span class='comment'># Your data goes here
|
137
137
|
</span><span class='rparen'>)</span>
|
138
138
|
</code></pre>
|
@@ -161,7 +161,7 @@ this:</p>
|
|
161
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
162
|
<span class='id identifier rubyid_type'>type</span> <span class='symbol'>:integer</span>
|
163
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'>'</span><span class='tstring_content'>
|
164
|
+
<span class='id identifier rubyid_req'>req</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>present</span><span class='tstring_end'>'</span></span> <span class='kw'>do</span>
|
165
165
|
<span class='id identifier rubyid_type'>type</span> <span class='symbol'>:boolean</span>
|
166
166
|
<span class='kw'>end</span>
|
167
167
|
<span class='kw'>end</span>
|
@@ -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
|
@@ -235,7 +261,7 @@ proc returns false."</p>
|
|
235
261
|
|
236
262
|
<p>The corresponding schema would look as follows:</p>
|
237
263
|
|
238
|
-
<pre class="code ruby"><code class="ruby"><span class='const'>
|
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>
|
239
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>
|
240
266
|
<span class='id identifier rubyid_type'>type</span> <span class='symbol'>:integer</span>
|
241
267
|
<span class='kw'>end</span>
|
@@ -256,8 +282,8 @@ the type checking, meaning that it only gets executed if the data has the right
|
|
256
282
|
type and the proc in <code>if</code> (if any) has returned true.</p>
|
257
283
|
|
258
284
|
<p>The proc passed to the <code>check</code> option is given the data being analyzed. It is to
|
259
|
-
return true if the data passes the custom check. If it returns false
|
260
|
-
considers the data to be invalid.</p>
|
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>
|
261
287
|
|
262
288
|
<p>The following example illustrates the use of the option <code>check</code>: Consider a
|
263
289
|
scenario in which you want the following rule set:</p>
|
@@ -278,10 +304,19 @@ scenario in which you want the following rule set:</p>
|
|
278
304
|
<p>The above Type Line has type <code>:string</code> and two options (<code>min</code> and <code>check</code>). The
|
279
305
|
option <code>min</code> is supported by the <code>:string</code> validator (covered later).</p>
|
280
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'>'</span><span class='tstring_content'>Custom error</span><span class='tstring_end'>'</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
|
+
|
281
316
|
<h3>Field Line</h3>
|
282
317
|
|
283
|
-
<p>Inside a Type Line of type <code>:hash</code
|
284
|
-
|
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>
|
285
320
|
|
286
321
|
<p>Field Lines start with one of the following six identifiers: <code>req</code>, <code>req?</code>,
|
287
322
|
<code>req!</code>, <code>opt</code>, <code>opt?</code> or <code>opt!</code>:</p>
|
@@ -327,6 +362,35 @@ non-nil field of type Integer or Date under the key <code>:age</code>.</p>
|
|
327
362
|
<p>You might find the notation cumbersome, and you'd be right to say so. Luckily
|
328
363
|
there are plenty of short forms available which we will see below.</p>
|
329
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'>'</span><span class='tstring_content'>name</span><span class='tstring_end'>'</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
|
+
|
330
394
|
<h2>Types</h2>
|
331
395
|
|
332
396
|
<p>Types are defined via their validators, which is a class under <code>validator/</code>.
|
@@ -357,31 +421,38 @@ Each validator is sourced by <code>schemacop.rb</code>.</p>
|
|
357
421
|
<li>supported options: <code>min</code>, <code>max</code> (bounds for string length)</li>
|
358
422
|
</ul></li>
|
359
423
|
<li><p><code>:symbol</code> accepts a Ruby Symbol.</p></li>
|
360
|
-
<li><p><code>:object</code> accepts an arbitrary Ruby object (any object if no option is given).</p>
|
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>
|
361
428
|
|
362
429
|
<ul>
|
363
|
-
<li
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
<
|
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>
|
370
437
|
|
371
438
|
<ul>
|
372
|
-
<li
|
373
|
-
<li>accepts a block with an arbitrary number of Type Lines.</li>
|
374
|
-
<li>TODO no lookahead for different arrays, see
|
375
|
-
validator_array_test#test_multiple_arrays</li>
|
439
|
+
<li><code>:array</code> accepts a Ruby Array.</li>
|
376
440
|
</ul></li>
|
377
|
-
<li><p
|
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>
|
378
445
|
|
379
446
|
<ul>
|
380
|
-
<li>accepts a
|
447
|
+
<li><code>:hash</code> accepts a Ruby Hash or an <code>ActiveSupport::HashWithIndifferentAccess</code>.</li>
|
381
448
|
</ul></li>
|
382
|
-
<li><p
|
449
|
+
<li><p>accepts a block with an arbitrary number of Field Lines.</p>
|
450
|
+
|
451
|
+
<ul>
|
452
|
+
<li><code>:nil</code>: accepts a Ruby NilClass instance. If you want to allow <code>nil</code> as a
|
383
453
|
value in a field, see above for the usage of the suffixes <code>-!</code> and <code>-?</code> for
|
384
|
-
Field Lines.</
|
454
|
+
Field Lines.</li>
|
455
|
+
</ul></li>
|
385
456
|
</ul>
|
386
457
|
|
387
458
|
<p>All types support the options <code>if</code> and <code>check</code> (see the section about Type Lines
|
@@ -495,6 +566,10 @@ write Field Lines in the schema instantiation:</p>
|
|
495
566
|
<span class='kw'>end</span>
|
496
567
|
</code></pre>
|
497
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
|
+
|
498
573
|
<h3>Shortform for subtypes</h3>
|
499
574
|
|
500
575
|
<p>In case of nested arrays, you can group all Type Lines to a single one.</p>
|
@@ -550,6 +625,145 @@ of type Array with children of type Array with children of type Hash in which at
|
|
550
625
|
least one of the Symbol keys <code>:food</code> and <code>:drink</code> (with any non-nil value type)
|
551
626
|
is present.</p>
|
552
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
|
+
|
553
767
|
<h2>Exceptions</h2>
|
554
768
|
|
555
769
|
<p>Schemacop will throw one of the following checked exceptions:</p>
|
@@ -578,6 +792,18 @@ needs to be given only if field <code>b</code> is present).</p></li>
|
|
578
792
|
<li><p>Schemacop does not yet support string regex matching.</p></li>
|
579
793
|
</ul>
|
580
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
|
+
|
581
807
|
<h2>Contributors</h2>
|
582
808
|
|
583
809
|
<p>Thanks to <a href="https://github.com/bbatsov/rubocop">Rubocop</a> for great inspiration
|
@@ -586,13 +812,13 @@ to <a href="http://www.subgit.com/">SubGit</a> for their great open source licen
|
|
586
812
|
|
587
813
|
<h2>Copyright</h2>
|
588
814
|
|
589
|
-
<p>Copyright (c)
|
815
|
+
<p>Copyright (c) 2019 Sitrox. See <code>LICENSE</code> for further details.</p>
|
590
816
|
</div></div>
|
591
817
|
|
592
818
|
<div id="footer">
|
593
|
-
Generated on
|
819
|
+
Generated on Mon Oct 28 16:21:59 2019 by
|
594
820
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
595
|
-
0.9.
|
821
|
+
0.9.20 (ruby-2.6.2).
|
596
822
|
</div>
|
597
823
|
|
598
824
|
</div>
|
data/doc/frames.html
CHANGED
data/doc/index.html
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
<title>
|
7
7
|
File: README
|
8
8
|
|
9
|
-
— Documentation by YARD 0.9.
|
9
|
+
— Documentation by YARD 0.9.20
|
10
10
|
|
11
11
|
</title>
|
12
12
|
|
@@ -132,7 +132,7 @@ around at runtime. Those two steps look as follows:</p>
|
|
132
132
|
|
133
133
|
<p>At runtime:</p>
|
134
134
|
|
135
|
-
<pre class="code ruby"><code class="ruby"><span class='id identifier
|
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
136
|
<span class='comment'># Your data goes here
|
137
137
|
</span><span class='rparen'>)</span>
|
138
138
|
</code></pre>
|
@@ -161,7 +161,7 @@ this:</p>
|
|
161
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
162
|
<span class='id identifier rubyid_type'>type</span> <span class='symbol'>:integer</span>
|
163
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'>'</span><span class='tstring_content'>
|
164
|
+
<span class='id identifier rubyid_req'>req</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>present</span><span class='tstring_end'>'</span></span> <span class='kw'>do</span>
|
165
165
|
<span class='id identifier rubyid_type'>type</span> <span class='symbol'>:boolean</span>
|
166
166
|
<span class='kw'>end</span>
|
167
167
|
<span class='kw'>end</span>
|
@@ -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
|
@@ -235,7 +261,7 @@ proc returns false."</p>
|
|
235
261
|
|
236
262
|
<p>The corresponding schema would look as follows:</p>
|
237
263
|
|
238
|
-
<pre class="code ruby"><code class="ruby"><span class='const'>
|
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>
|
239
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>
|
240
266
|
<span class='id identifier rubyid_type'>type</span> <span class='symbol'>:integer</span>
|
241
267
|
<span class='kw'>end</span>
|
@@ -256,8 +282,8 @@ the type checking, meaning that it only gets executed if the data has the right
|
|
256
282
|
type and the proc in <code>if</code> (if any) has returned true.</p>
|
257
283
|
|
258
284
|
<p>The proc passed to the <code>check</code> option is given the data being analyzed. It is to
|
259
|
-
return true if the data passes the custom check. If it returns false
|
260
|
-
considers the data to be invalid.</p>
|
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>
|
261
287
|
|
262
288
|
<p>The following example illustrates the use of the option <code>check</code>: Consider a
|
263
289
|
scenario in which you want the following rule set:</p>
|
@@ -278,10 +304,19 @@ scenario in which you want the following rule set:</p>
|
|
278
304
|
<p>The above Type Line has type <code>:string</code> and two options (<code>min</code> and <code>check</code>). The
|
279
305
|
option <code>min</code> is supported by the <code>:string</code> validator (covered later).</p>
|
280
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'>'</span><span class='tstring_content'>Custom error</span><span class='tstring_end'>'</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
|
+
|
281
316
|
<h3>Field Line</h3>
|
282
317
|
|
283
|
-
<p>Inside a Type Line of type <code>:hash</code
|
284
|
-
|
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>
|
285
320
|
|
286
321
|
<p>Field Lines start with one of the following six identifiers: <code>req</code>, <code>req?</code>,
|
287
322
|
<code>req!</code>, <code>opt</code>, <code>opt?</code> or <code>opt!</code>:</p>
|
@@ -327,6 +362,35 @@ non-nil field of type Integer or Date under the key <code>:age</code>.</p>
|
|
327
362
|
<p>You might find the notation cumbersome, and you'd be right to say so. Luckily
|
328
363
|
there are plenty of short forms available which we will see below.</p>
|
329
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'>'</span><span class='tstring_content'>name</span><span class='tstring_end'>'</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
|
+
|
330
394
|
<h2>Types</h2>
|
331
395
|
|
332
396
|
<p>Types are defined via their validators, which is a class under <code>validator/</code>.
|
@@ -357,31 +421,38 @@ Each validator is sourced by <code>schemacop.rb</code>.</p>
|
|
357
421
|
<li>supported options: <code>min</code>, <code>max</code> (bounds for string length)</li>
|
358
422
|
</ul></li>
|
359
423
|
<li><p><code>:symbol</code> accepts a Ruby Symbol.</p></li>
|
360
|
-
<li><p><code>:object</code> accepts an arbitrary Ruby object (any object if no option is given).</p>
|
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>
|
361
428
|
|
362
429
|
<ul>
|
363
|
-
<li
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
<
|
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>
|
370
437
|
|
371
438
|
<ul>
|
372
|
-
<li
|
373
|
-
<li>accepts a block with an arbitrary number of Type Lines.</li>
|
374
|
-
<li>TODO no lookahead for different arrays, see
|
375
|
-
validator_array_test#test_multiple_arrays</li>
|
439
|
+
<li><code>:array</code> accepts a Ruby Array.</li>
|
376
440
|
</ul></li>
|
377
|
-
<li><p
|
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>
|
378
445
|
|
379
446
|
<ul>
|
380
|
-
<li>accepts a
|
447
|
+
<li><code>:hash</code> accepts a Ruby Hash or an <code>ActiveSupport::HashWithIndifferentAccess</code>.</li>
|
381
448
|
</ul></li>
|
382
|
-
<li><p
|
449
|
+
<li><p>accepts a block with an arbitrary number of Field Lines.</p>
|
450
|
+
|
451
|
+
<ul>
|
452
|
+
<li><code>:nil</code>: accepts a Ruby NilClass instance. If you want to allow <code>nil</code> as a
|
383
453
|
value in a field, see above for the usage of the suffixes <code>-!</code> and <code>-?</code> for
|
384
|
-
Field Lines.</
|
454
|
+
Field Lines.</li>
|
455
|
+
</ul></li>
|
385
456
|
</ul>
|
386
457
|
|
387
458
|
<p>All types support the options <code>if</code> and <code>check</code> (see the section about Type Lines
|
@@ -495,6 +566,10 @@ write Field Lines in the schema instantiation:</p>
|
|
495
566
|
<span class='kw'>end</span>
|
496
567
|
</code></pre>
|
497
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
|
+
|
498
573
|
<h3>Shortform for subtypes</h3>
|
499
574
|
|
500
575
|
<p>In case of nested arrays, you can group all Type Lines to a single one.</p>
|
@@ -550,6 +625,145 @@ of type Array with children of type Array with children of type Hash in which at
|
|
550
625
|
least one of the Symbol keys <code>:food</code> and <code>:drink</code> (with any non-nil value type)
|
551
626
|
is present.</p>
|
552
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
|
+
|
553
767
|
<h2>Exceptions</h2>
|
554
768
|
|
555
769
|
<p>Schemacop will throw one of the following checked exceptions:</p>
|
@@ -578,6 +792,18 @@ needs to be given only if field <code>b</code> is present).</p></li>
|
|
578
792
|
<li><p>Schemacop does not yet support string regex matching.</p></li>
|
579
793
|
</ul>
|
580
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
|
+
|
581
807
|
<h2>Contributors</h2>
|
582
808
|
|
583
809
|
<p>Thanks to <a href="https://github.com/bbatsov/rubocop">Rubocop</a> for great inspiration
|
@@ -586,13 +812,13 @@ to <a href="http://www.subgit.com/">SubGit</a> for their great open source licen
|
|
586
812
|
|
587
813
|
<h2>Copyright</h2>
|
588
814
|
|
589
|
-
<p>Copyright (c)
|
815
|
+
<p>Copyright (c) 2019 Sitrox. See <code>LICENSE</code> for further details.</p>
|
590
816
|
</div></div>
|
591
817
|
|
592
818
|
<div id="footer">
|
593
|
-
Generated on
|
819
|
+
Generated on Mon Oct 28 16:21:59 2019 by
|
594
820
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
595
|
-
0.9.
|
821
|
+
0.9.20 (ruby-2.6.2).
|
596
822
|
</div>
|
597
823
|
|
598
824
|
</div>
|