data-validator 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 43e341fbbededef9b22873786e968cbc88b4e792
4
+ data.tar.gz: 23e63129a76bebe6673f554851107b35ff7a69d7
5
+ SHA512:
6
+ metadata.gz: ca0a84a63e3ec0b129a8c3edfdf5ef00f381710b22189b886855085c880d44a8feb0aa404d674aff4ef5357045c4036fdd9854fd6125fd277359863c2125ed63
7
+ data.tar.gz: 8fc856b878d892559a1863d1460955964c0617a87d0bb713f3ce85e8bd8c952020797e8f2b34f305969a2fb42865bda5155dc07593d87b39d3343d69847fe28c
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,25 @@
1
+ #! /your/favourite/path/to/bundler
2
+ # -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level 2 -*-
3
+
4
+ # Copyright (c) 2014 Urabe, Shyouhei
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+
24
+ source 'https://rubygems.org'
25
+ gemspec require: false
data/LICENSE.txt ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2014 Urabe, Shyouhei
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+ of the Software, and to permit persons to whom the Software is furnished to do
8
+ so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be
11
+ included in all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,53 @@
1
+ This is a Ruby version of [gfx/p5-Data-Validator](https://github.com/gfx/p5-Data-Validator) + [xaicron/p5-Data-Validator-Recursive](https://github.com/xaicron/p5-Data-Validator-Recursive).
2
+
3
+ Compare below versus https://metacpan.org/pod/Data::Validator
4
+
5
+ ```ruby
6
+ rule = Data::Validator.new(
7
+ 'uri' => { isa: String, xor: %w(schema host path_query) },
8
+ 'schema' => { isa: String, default: 'http' },
9
+ 'host' => { isa: String },
10
+ 'path_query' => { isa: String, default: '/' },
11
+ 'method' => { isa: String, default: 'GET' },
12
+ )
13
+
14
+ args = rule.validate('uri' => 'http://example.com')
15
+ ```
16
+
17
+ and below versus https://metacpan.org/pod/Data::Validator::Recursive
18
+
19
+ ```ruby
20
+ # create a new rule
21
+ rule = Data::Validator::Recursive.new(
22
+ 'foo' => String,
23
+ 'bar' => { isa: Integer },
24
+ 'baz' => {
25
+ isa: Hash, # default
26
+ rule: {
27
+ 'hoge' => { isa: String, optional: 1 },
28
+ 'fuga' => Integer
29
+ },
30
+ },
31
+ )
32
+
33
+ # input data for validation
34
+ input = {
35
+ 'foo' => 'hoge',
36
+ 'bar' => 1192,
37
+ 'baz' => {
38
+ 'hoge' => 'kamakura',
39
+ 'fuga' => 1185,
40
+ },
41
+ }
42
+
43
+ # do validation
44
+ params = rule.validate(input) # raises automatically on error
45
+ ```
46
+
47
+ #### limitations
48
+ - `Data::Validator` is recursive by default. There is no such thing like a nonrecursive validator.
49
+ - `->with('Method')` does not make sense to us, so not supported.
50
+ - `does` also does not make sense. Not supported.
51
+ - We do distinguish arrays and hashes unlike perl. There also are no `->with('Sequenced')`.
52
+ - I don't understand the actual needs of `xor`; all examples seems illustravive to me. Other validators like JSON Schema (cf [zigorou/perl-JSV](https://github.com/zigorou/perl-JSV)) do not have this. This lack of understanding can negatively impact.
53
+ - I don't understand why @gfx thinks it's fast.
data/Rakefile ADDED
@@ -0,0 +1,77 @@
1
+ #! /your/favourite/path/to/rake
2
+ # -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level 2 -*-
3
+
4
+ # Copyright (c) 2014 Urabe, Shyouhei
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+
24
+ begin
25
+ require 'rubygems'
26
+ require 'bundler/setup'
27
+ require 'rake'
28
+ rescue Exception => e
29
+ $stderr.puts e.message
30
+ $stderr.puts "Run `bundle install` to install missing gems"
31
+ exit false
32
+ else
33
+ begin
34
+ Bundler.setup :default
35
+ rescue Bundler::BundlerError => e
36
+ $stderr.puts e.message
37
+ $stderr.puts "Run `bundle install` to install missing gems"
38
+ exit e.status_code
39
+ end
40
+ end
41
+
42
+ begin
43
+ Bundler.setup :development
44
+ require 'yard'
45
+ require 'bundler/gem_tasks'
46
+ require 'rake/testtask'
47
+
48
+ YARD::Rake::YardocTask.new
49
+
50
+ task default: :test
51
+ task spec: :test
52
+ desc "run tests"
53
+ Rake::TestTask.new do |t|
54
+ t.test_files = FileList['test/**/*.rb']
55
+ end
56
+ rescue LoadError, NameError
57
+ # OK, they can be absent on non-development mode.
58
+ end
59
+
60
+ desc "a la rails console"
61
+ task :console do
62
+ require_relative 'lib/data/validator'
63
+ require 'irb'
64
+ require 'irb/completion'
65
+ ARGV.clear
66
+ IRB.start
67
+ end
68
+ task :c => :console
69
+
70
+ desc "pry console"
71
+ task :pry do
72
+ require_relative 'lib/data/validator'
73
+ require 'pry'
74
+ ARGV.clear
75
+ Pry.start
76
+ end
77
+
@@ -0,0 +1,56 @@
1
+ #! /your/favourite/path/to/gem
2
+ # -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level 2 -*-
3
+
4
+ # Copyright (c) 2014 Urabe, Shyouhei
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+
24
+ # hack avoid namespace pollution
25
+ path = File.expand_path 'lib/data/validator/version.rb', __dir__
26
+ content = File.read path
27
+ version = Module.new.module_eval <<-'end'
28
+ Data = Module.new
29
+ Data::Validator = Module.new
30
+ eval content, binding, path
31
+ end
32
+
33
+ Gem::Specification.new do |spec|
34
+ spec.name = "data-validator"
35
+ spec.version = version
36
+ spec.authors = ["Urabe, Shyouhei"]
37
+ spec.email = ["shyouhei@ruby-lang.org"]
38
+ spec.summary = "p5-Data-Validator / p5-Data-Validator-Recursive port"
39
+ spec.description = "for gfx fan and xaicron fan"
40
+ spec.homepage = "https://metacpan.org/pod/Data::Validator"
41
+ spec.license = "MIT"
42
+
43
+ spec.files = `git ls-files -z`.split("\x0")
44
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
45
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
46
+ spec.require_paths = ["lib"]
47
+
48
+ # spec.required_ruby_version = '~> 2.1'
49
+ spec.add_development_dependency 'bundler', '~> 1.7'
50
+ spec.add_development_dependency 'rake', '~> 10.3'
51
+ spec.add_development_dependency 'rdoc', '~> 4.0'
52
+ spec.add_development_dependency 'yard', '~> 0.8'
53
+ spec.add_development_dependency 'test-unit', '~> 3.0'
54
+ spec.add_development_dependency 'simplecov', '>= 0'
55
+ spec.add_development_dependency 'pry', '~> 0.10'
56
+ end
@@ -0,0 +1,24 @@
1
+ #! /your/favourite/path/to/ruby
2
+ # -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level 2 -*-
3
+
4
+ # Copyright (c) 2014 Urabe, Shyouhei
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+
24
+ Data::Validator::Error = Class.new StandardError # Validation failures
@@ -0,0 +1,24 @@
1
+ #! /your/favourite/path/to/ruby
2
+ # -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level 2 -*-
3
+
4
+ # Copyright (c) 2014 Urabe, Shyouhei
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+
24
+ Data::Validator::Recursive = Data::Validator # for xaicron fans
@@ -0,0 +1,23 @@
1
+ #! /your/favourite/path/to/ruby
2
+ # -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level 2 -*-
3
+
4
+ # Copyright (c) 2014 Urabe, Shyouhei
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+ Data::Validator::VERSION = "1.0.0"
@@ -0,0 +1,232 @@
1
+ #! /your/favourite/path/to/ruby
2
+ # -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level 2 -*-
3
+
4
+ # Copyright (c) 2014 Urabe, Shyouhei
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+ Data::Validator = Class.new # @!parse class Data::Validator; end
24
+ require_relative "validator/version"
25
+
26
+ class Data::Validator
27
+
28
+ class << self
29
+ alias bare_new new
30
+ private :bare_new
31
+
32
+ # Creates a new validator.
33
+ #
34
+ # @overload new(hash)
35
+ # This is the basic validator that validates one hash
36
+ #
37
+ # @param [Hash] hash Describes validation rule.
38
+ # @return [Data::Validator] Constructed validator.
39
+ #
40
+ # @overload new(array)
41
+ # What a `->with('Sequenced')` intends in perl version. In perl a
42
+ # `(...)` can either be an array or a hash but in ruby they are
43
+ # different.
44
+ #
45
+ # @param [<Hash>] array Describes validation rule.
46
+ # @return [Data::Validator] Constructed validator.
47
+ #
48
+ # @overload new(validator)
49
+ # For recursive call.
50
+ #
51
+ # @param [Data::Validator] validator A validator instance.
52
+ # @return [Data::Validator] The argument.
53
+ #
54
+ # @overload new(object)
55
+ # Arbitrary objects can be specified, for simplicity.
56
+ #
57
+ # @param [Object] object Anything.
58
+ # @return [Data::Validator] Valudator that matches it.
59
+ def new rule
60
+ case rule
61
+ when self then rule # already
62
+ when Hash then bare_new isa: Hash, rule: rule
63
+ when Array then bare_new isa: Array, rule: rule
64
+ else bare_new isa: rule
65
+ end
66
+ end
67
+ end
68
+
69
+ # (Maybe recursively) constructs a validator.
70
+ #
71
+ # @param [Hash] rule Describes validation rule.
72
+ # @option rule [String] isa Class to match.
73
+ # @option rule [<String>] :xor ??? (please ask gfx).
74
+ # @option rule [Object] :default Default value.
75
+ # @option rule [true,false] :option Omitable or not.
76
+ # @option rule [true,false] :allow_extra Can have others or not.
77
+ # @option rule [Hash] :rule Recursion rule.
78
+ def initialize(**rule)
79
+ @isa = rule.delete(:isa) || Object # ??
80
+ @rule = rule
81
+ if rule.has_key? :rule then
82
+ raise TypeError, "rule must be a hash" unless rule[:rule].is_a? Hash
83
+
84
+ case
85
+ when @isa == Hash then
86
+ recur = rule[:rule].each_pair.each_with_object Hash.new do |(k, v), r|
87
+ case v when Hash then
88
+ r[k] = self.class.send :bare_new, v
89
+ else
90
+ r[k] = self.class.send :bare_new, isa: v
91
+ end
92
+ end
93
+ @rule = rule.merge rule: recur
94
+ when @isa == Array then
95
+ recur = self.class.new rule[:rule]
96
+ @rule = rule.merge rule: recur
97
+ end
98
+ end
99
+ end
100
+
101
+ # Validates the input
102
+ #
103
+ # @note this does not modify the validator, but does modify the argument
104
+ # object.
105
+ #
106
+ # @param [Object] actual Thing to validate.
107
+ # @return [Object] The argument, validated and filled defaults.
108
+ def validate actual = @isa.new
109
+ case actual when @isa then
110
+ if @rule.has_key? :rule then
111
+ case
112
+ when @isa == Hash then return validate_hash actual
113
+ when @isa == Array then return validate_array actual
114
+ else raise RuntimeError, "[bug] notreached"
115
+ end
116
+ else
117
+ return actual
118
+ end
119
+ else
120
+ raise Error, "type mismatch"
121
+ end
122
+ end
123
+
124
+ # add options
125
+ # @return self
126
+ # @param ['AllowExtra'] extension 'AllowExtra' only for now
127
+ def with extension
128
+ case extension
129
+ when 'AllowExtra' then
130
+ @rule[:allow_extra] = true
131
+ else
132
+ raise ArgumentError, "unsupported extension #{extension}"
133
+ end
134
+ return self
135
+ end
136
+
137
+ protected
138
+ def [] key
139
+ @rule[key]
140
+ end
141
+
142
+ def has_key? key
143
+ @rule.has_key? key
144
+ end
145
+
146
+ private
147
+ def validate_hash actual
148
+ xor = Array.new
149
+ missing = Array.new
150
+ fillin = Array.new
151
+ @rule[:rule].each_pair do |key, rule|
152
+ if actual.has_key? key then
153
+ begin
154
+ actual[key] = rule.validate actual[key]
155
+ rescue Error => err
156
+ raise Error, "#{key}:#{err}"
157
+ end
158
+ if exclude = rule[:xor] then
159
+ if (actual.keys & exclude).empty? then
160
+ xor.concat exclude
161
+ else
162
+ raise Error, "#{key} versus #{exclude.inspect} are exclusive"
163
+ end
164
+ end
165
+ elsif rule.has_key? :default then
166
+ fillin << key
167
+ elsif rule[:optional] then
168
+ # ok
169
+ elsif @rule[:allow_extra] then
170
+ # ok
171
+ else
172
+ missing << key
173
+ end
174
+ end
175
+ fillin.reject! {|i| xor.include? i }
176
+ fillin.each do |k|
177
+ rule = @rule[:rule][k]
178
+ case default = rule[:default] when Proc then
179
+ defval = default.(self, rule, actual)
180
+ else
181
+ defval = default
182
+ end
183
+ actual[k] = defval
184
+ end
185
+ unless missing.empty?
186
+ # SLOW PASS find matching xor
187
+ xor_map = @rule[:rule].each_pair.inject Hash.new do |r, (k, v)|
188
+ if v[:xor] then
189
+ v[:xor].each do |kk|
190
+ r[kk] ||= []
191
+ r[kk] << k
192
+ r[k] ||= []
193
+ r[k] << kk
194
+ end
195
+ end
196
+ r
197
+ end
198
+ if missing.any? {|i| not xor_map[i] } then
199
+ raise Error, "#{missing.inspect} missing"
200
+ end
201
+ x = y = nil
202
+ if missing.any? {|i|
203
+ xor_map[i].any? {|j|
204
+ if missing.include? j then
205
+ x = i
206
+ y = j
207
+ true
208
+ end
209
+ }
210
+ } then
211
+ raise Error, "#{x} or #{y} missing"
212
+ end
213
+ end
214
+ return actual
215
+ end
216
+
217
+ def validate_array actuals
218
+ rule = @rule[:rule]
219
+ actuals.each_index do |index|
220
+ begin
221
+ rule.validate actuals[index]
222
+ rescue Error => err
223
+ raise Error, "##{index}:#{err}"
224
+ end
225
+ end
226
+
227
+ return actuals
228
+ end
229
+ end
230
+
231
+ require_relative 'validator/recursive'
232
+ require_relative 'validator/Error'
@@ -0,0 +1,9 @@
1
+ require 'test-unit'
2
+
3
+ class Test000Load < Test::Unit::TestCase
4
+ def test_require
5
+ assert_nothing_raised do
6
+ require 'data/validator'
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,29 @@
1
+ require 'test-unit'
2
+ require 'data/validator'
3
+
4
+ class Test001Basic < Test::Unit::TestCase
5
+
6
+ def test_test
7
+ v = Data::Validator.new(
8
+ 'foo' => Numeric
9
+ )
10
+ assert { v.is_a? Data::Validator }
11
+
12
+ args = v.validate({ 'foo' => 42 })
13
+ assert { args == { 'foo' => 42 } }
14
+
15
+ args = v.validate({ 'foo' => 3.14 })
16
+ assert { args == { 'foo' => 3.14 } }
17
+
18
+ args = v.validate( 'foo' => 3.14 )
19
+ assert { args == { 'foo' => 3.14 } }
20
+
21
+ # note 'failing cases';
22
+
23
+ assert_raise_message(/foo/) { v.validate() }
24
+ assert_raise_message(/foo/) { v.validate({'foo' => 'bar'}) }
25
+ assert_raise_message(/baz|qux/) {
26
+ v.validate({'foo' => 0, 'baz' => 42, qux => 100 })
27
+ }
28
+ end
29
+ end
@@ -0,0 +1,23 @@
1
+ require 'test-unit'
2
+ require 'data/validator'
3
+
4
+ class Test002Isa < Test::Unit::TestCase
5
+
6
+ def test_test
7
+ v = Data::Validator.new(
8
+ 'foo' => { isa: Numeric },
9
+ )
10
+ assert { v.is_a? Data::Validator }
11
+
12
+ args = v.validate({ 'foo' => 42 })
13
+ assert { args == { 'foo' => 42 } }
14
+
15
+ args = v.validate({ 'foo' => 3.14 })
16
+ assert { args == { 'foo' => 3.14 } }
17
+
18
+ # note 'failing cases';
19
+
20
+ assert_raise_message(/foo/) { v.validate() }
21
+ assert_raise_message(/foo/) { v.validate({'foo' => 'bar'}) }
22
+ end
23
+ end
@@ -0,0 +1,34 @@
1
+ require 'test-unit'
2
+ require 'data/validator'
3
+
4
+ class Test003Default < Test::Unit::TestCase
5
+
6
+ def test_test
7
+ v = Data::Validator.new(
8
+ 'foo' => { isa: Numeric, default: 99 },
9
+ )
10
+ assert { v.is_a? Data::Validator }
11
+
12
+ args = v.validate({ 'foo' => 42 })
13
+ assert { args == { 'foo' => 42 } }
14
+
15
+ args = v.validate({})
16
+ assert { args == { 'foo' => 99 } }
17
+
18
+ args = v.validate()
19
+ assert { args == { 'foo' => 99 } }
20
+
21
+ v = Data::Validator.new(
22
+ 'foo' => { isa: Numeric, default: 99 },
23
+ 'bar' => { isa: Numeric, default: -> (validator, rule, args) {
24
+ args['foo'] + 1
25
+ } },
26
+ )
27
+
28
+ args = v.validate()
29
+ assert { args == { 'foo' => 99, 'bar' => 100 } }
30
+
31
+ args = v.validate('foo' => 42)
32
+ assert { args == { 'foo' => 42, 'bar' => 43 } }
33
+ end
34
+ end