schemacop 2.1.0 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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>
|