jsexp 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|