jsexp 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +14 -1
- data/lib/jsexp.rb +42 -28
- data/test/jsexp_test.rb +22 -12
- metadata +2 -2
data/README.md
CHANGED
@@ -13,7 +13,7 @@ Example
|
|
13
13
|
schema = {
|
14
14
|
'name' => String, # case expression
|
15
15
|
'email' => /@/, # case expression
|
16
|
-
'p' => (0.0..1.0), #
|
16
|
+
'p' => (0.0..1.0), # definite range
|
17
17
|
'id' => [:range, [0, :inf]], # indefinite range
|
18
18
|
'color' => [:enum, ['red', 'green', 'blue']], # enum
|
19
19
|
'offset' => [:tuple, [Float, Float]], # exact-size array
|
@@ -46,3 +46,16 @@ Non-features
|
|
46
46
|
- nested schemas: This is a source of arbitrary complexity.
|
47
47
|
- specific error messages: Refer to the schema to see what's wrong.
|
48
48
|
- lambdas: Do more complex validation yourself.
|
49
|
+
|
50
|
+
Float Promotion
|
51
|
+
---------------
|
52
|
+
|
53
|
+
Javascript does not distinguish between integer and float. To accomodate, we accept integers or floats for type Float.
|
54
|
+
|
55
|
+
Numeric Ranges
|
56
|
+
--------------
|
57
|
+
|
58
|
+
- (0..10): integers 0, 1, ..., 10 # to_a
|
59
|
+
- (0.0..10.0): floats [0.0, 10.0]
|
60
|
+
- [:range, [0, :inf]]: integers 0, 1, ...
|
61
|
+
- [:range, [0.0, :inf]]: floats [0.0, inf)
|
data/lib/jsexp.rb
CHANGED
@@ -1,35 +1,49 @@
|
|
1
1
|
module JSExp
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
2
|
+
def JSExp.valid?(schema, obj)
|
3
|
+
if schema.is_a?(Hash)
|
4
|
+
obj.is_a?(Hash) && schema.map {|key, schema_|
|
5
|
+
if schema_.is_a?(Array) && schema_[0] == :optional
|
6
|
+
!obj.key?(key) || valid?(schema_[1], obj[key])
|
7
|
+
else
|
8
|
+
obj.key?(key) && valid?(schema_, obj[key])
|
9
|
+
end
|
10
|
+
}.all?
|
11
|
+
elsif schema.is_a?(Array)
|
12
|
+
case schema[0]
|
13
|
+
when :array
|
14
|
+
obj.is_a?(Array) && obj.map {|x| valid?(schema[1], x)}.all?
|
15
|
+
when :enum
|
16
|
+
schema[1].include?(obj)
|
17
|
+
when :range
|
18
|
+
min, max = schema[1]
|
19
|
+
bound = (min == :inf ? max : min)
|
20
|
+
same_domain?(bound, obj) &&
|
21
|
+
(min == :inf ? true : obj >= min) &&
|
22
|
+
(max == :inf ? true : obj <= max)
|
23
|
+
when :tuple
|
24
|
+
obj.is_a?(Array) && obj.size == schema[1].size && schema[1].each_index.map {|i| valid?(schema[1][i], obj[i])}.all?
|
25
|
+
end
|
26
|
+
elsif schema.is_a?(Range)
|
27
|
+
same_domain?(schema.min, obj) && schema.include?(obj)
|
28
|
+
elsif schema == Float
|
29
|
+
obj.is_a?(Integer) || obj.is_a?(Float)
|
30
|
+
else
|
31
|
+
case obj
|
32
|
+
when schema
|
33
|
+
true
|
8
34
|
else
|
9
|
-
|
35
|
+
false
|
10
36
|
end
|
11
|
-
}.all?
|
12
|
-
elsif schema.is_a?(Array)
|
13
|
-
case schema[0]
|
14
|
-
when :array
|
15
|
-
obj.is_a?(Array) && obj.map {|x| valid?(schema[1], x)}.all?
|
16
|
-
when :enum
|
17
|
-
schema[1].include?(obj)
|
18
|
-
when :range
|
19
|
-
min, max = schema[1]
|
20
|
-
(min == :inf ? true : obj.class == min.class && obj >= min) &&
|
21
|
-
(max == :inf ? true : obj.class == max.class && obj <= max)
|
22
|
-
when :tuple
|
23
|
-
obj.is_a?(Array) && obj.size == schema[1].size && schema[1].each_index.map {|i| valid?(schema[1][i], obj[i])}.all?
|
24
37
|
end
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
38
|
+
end
|
39
|
+
private
|
40
|
+
def JSExp.same_domain?(schema, obj)
|
41
|
+
# y.is_a?(x.class) fails when y.class == Bignum and x.class == Fixnum
|
42
|
+
case schema
|
43
|
+
when Integer
|
44
|
+
JSExp.valid?(Integer, obj)
|
45
|
+
when Float
|
46
|
+
JSExp.valid?(Float, obj)
|
31
47
|
end
|
32
48
|
end
|
33
49
|
end
|
34
|
-
|
35
|
-
end
|
data/test/jsexp_test.rb
CHANGED
@@ -8,25 +8,20 @@ describe JSExp do
|
|
8
8
|
JSExp.valid?(String, 0).must_equal false
|
9
9
|
|
10
10
|
JSExp.valid?(Integer, 0).must_equal true
|
11
|
-
JSExp.valid?(Integer,
|
11
|
+
JSExp.valid?(Integer, '').must_equal false
|
12
12
|
|
13
13
|
JSExp.valid?(Float, 0.0).must_equal true
|
14
|
-
JSExp.valid?(Float,
|
14
|
+
JSExp.valid?(Float, '').must_equal false
|
15
15
|
|
16
16
|
JSExp.valid?(/@/, 'user@example.com').must_equal true
|
17
17
|
JSExp.valid?(/@/, '').must_equal false
|
18
|
-
|
19
|
-
JSExp.valid?((0..10), 5).must_equal true
|
20
|
-
JSExp.valid?((0..10), 11).must_equal false
|
21
|
-
|
22
|
-
JSExp.valid?((0.0..1.0), 0.5).must_equal true
|
23
|
-
JSExp.valid?((0.0..1.0), 1.1).must_equal false
|
24
18
|
end
|
25
19
|
|
26
20
|
it 'validates indefinite arrays' do
|
27
21
|
JSExp.valid?([:array, Integer], []).must_equal true
|
28
22
|
JSExp.valid?([:array, Integer], [0]).must_equal true
|
29
23
|
JSExp.valid?([:array, Integer], [0, 0]).must_equal true
|
24
|
+
|
30
25
|
JSExp.valid?([:array, Integer], [0.0]).must_equal false
|
31
26
|
JSExp.valid?([:array, Integer], [0, 0.0]).must_equal false
|
32
27
|
end
|
@@ -44,15 +39,19 @@ describe JSExp do
|
|
44
39
|
JSExp.valid?(schema, {'id' => 0}).must_equal false
|
45
40
|
end
|
46
41
|
|
42
|
+
it 'validates definite ranges' do
|
43
|
+
JSExp.valid?((0..10), 5).must_equal true
|
44
|
+
JSExp.valid?((0..10), 11).must_equal false
|
45
|
+
|
46
|
+
JSExp.valid?((0.0..1.0), 0.5).must_equal true
|
47
|
+
JSExp.valid?((0.0..1.0), 1.1).must_equal false
|
48
|
+
end
|
49
|
+
|
47
50
|
it 'validates indefinite ranges' do
|
48
51
|
JSExp.valid?([:range, [0, :inf]], 0).must_equal true
|
49
52
|
JSExp.valid?([:range, [0, :inf]], -1).must_equal false
|
50
|
-
JSExp.valid?([:range, [0, :inf]], 0.0).must_equal false
|
51
53
|
|
52
54
|
JSExp.valid?([:range, [:inf, 0]], 0).must_equal true
|
53
|
-
JSExp.valid?([:range, [:inf, 0]], 1).must_equal false
|
54
|
-
|
55
|
-
JSExp.valid?([:range, [:inf, :inf]], 0).must_equal true
|
56
55
|
end
|
57
56
|
|
58
57
|
it 'validates tuples' do
|
@@ -61,4 +60,15 @@ describe JSExp do
|
|
61
60
|
JSExp.valid?([:tuple, [Integer, Float]], [0]).must_equal false
|
62
61
|
JSExp.valid?([:tuple, [Integer, Float]], [0, 0.0, 0]).must_equal false
|
63
62
|
end
|
63
|
+
|
64
|
+
it 'handles float promotion' do
|
65
|
+
JSExp.valid?(Float, 0).must_equal true
|
66
|
+
JSExp.valid?(Integer, 0.0).must_equal false
|
67
|
+
|
68
|
+
JSExp.valid?((0.0..10.0), 5).must_equal true
|
69
|
+
JSExp.valid?((0..10), 5.0).must_equal false
|
70
|
+
|
71
|
+
JSExp.valid?([:range, [0.0, :inf]], 5).must_equal true
|
72
|
+
JSExp.valid?([:range, [0, :inf]], 5.0).must_equal false
|
73
|
+
end
|
64
74
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jsexp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -41,7 +41,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
41
41
|
version: '0'
|
42
42
|
requirements: []
|
43
43
|
rubyforge_project:
|
44
|
-
rubygems_version: 1.8.
|
44
|
+
rubygems_version: 1.8.15
|
45
45
|
signing_key:
|
46
46
|
specification_version: 3
|
47
47
|
summary: json schemas
|