jschematic 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ == 0.0.2
2
+ * Refactored Properties and PatternProperties so the latter inherits from the former (Mike Sassak)
3
+ * Simple IPv4 CIDR format support (Mike Sassak)
4
+ * Extracted Composite mixin and refactored Schema and Properties to use it (Mike Sassak)
5
+
6
+ == 0.0.1
7
+ * First release (Mike Sassak)
@@ -15,7 +15,6 @@ Feature: Core schema: default
15
15
  "name": "Gristle Thornbody"
16
16
  }
17
17
  }
18
-
19
18
  """
20
19
  Then '{ "age": 35 }' is valid JSON
21
20
 
@@ -23,6 +23,21 @@ Feature: Core schema: format
23
23
  | "" |
24
24
  | "fe80::202:b3ff:fe1e:8329" |
25
25
 
26
+ Scenario: IPv4 CIDR
27
+ When the schema is:
28
+ """
29
+ {
30
+ "type": "string",
31
+ "format": "cidr"
32
+ }
33
+ """
34
+ Then '"192.168.0.1/23"' is valid JSON
35
+ But these are not valid JSON:
36
+ | "" |
37
+ | "192.168.0.1" |
38
+ | "6.7.8.9/0" |
39
+ | "1.2.3.4/33" |
40
+
26
41
  Scenario: IPv6
27
42
  When the schema is:
28
43
  """
@@ -13,6 +13,50 @@ Feature: Core schema: patternProperties
13
13
  | { "name": "Felizberto" } |
14
14
  | { "firstName": "Fitzheraldo" } |
15
15
  | { "fullName": "Inigo Montoya" } |
16
+ | { "doesNotMatch": 12345678 } |
16
17
  But these are not valid JSON:
17
- | { "name": 2112 } |
18
- | { "named": "Werner" } |
18
+ | { "name": 2112 } |
19
+ | { "aNiceName": [1,2,3] } |
20
+
21
+ Scenario: multiple patterns
22
+ When the schema is:
23
+ """
24
+ {
25
+ "patternProperties": {
26
+ "^foos": { "type": "string" },
27
+ "umber$": { "type": "integer" }
28
+ }
29
+ }
30
+ """
31
+ Then these are valid JSON:
32
+ | { "foosball": "is a silly game" } |
33
+ | { "number": 2112 } |
34
+ But these are not valid JSON:
35
+ | { "humber": "Fourty-two" } |
36
+ | { "foos": 2112 } |
37
+
38
+ Scenario: pattern with vanilla property
39
+ When the schema is:
40
+ """
41
+ {
42
+ "properties": {
43
+ "a": { "type": "string" }
44
+ },
45
+
46
+ "patternProperties": {
47
+ "a": { "enum": ["fnord", 42] }
48
+ }
49
+ }
50
+ """
51
+ Then this is valid JSON:
52
+ """
53
+ {
54
+ "a": "fnord",
55
+ "apple": 42,
56
+ "aardvark": "fnord"
57
+ }
58
+ """
59
+ But these are not valid JSON:
60
+ | { "a": 42 } |
61
+ | { "apple": "6 * 9" } |
62
+ | { "aardvark": 41 } |
@@ -85,7 +85,7 @@ Feature: Core Schema: properties & additionalProperties
85
85
  }
86
86
  """
87
87
 
88
- Scenario: additionalProperties defined by a schema
88
+ Scenario: additionalProperties defined by a schema
89
89
  When the schema is:
90
90
  """
91
91
  {
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'jschematic'
3
- s.version = '0.0.1'
3
+ s.version = '0.0.2'
4
4
  s.authors = ["Mike Sassak"]
5
5
  s.description = "JSON Schema v3 Validator"
6
6
  s.summary = "jschematic #{s.version}"
@@ -10,6 +10,8 @@ module Jschematic
10
10
  Uri.new
11
11
  when "ip-address", "ipv6"
12
12
  Ip.new(format)
13
+ when "cidr"
14
+ Cidr.new(format)
13
15
  else
14
16
  NullFormat.new
15
17
  end
@@ -44,6 +46,16 @@ module Jschematic
44
46
  end
45
47
  end
46
48
 
49
+ class Cidr
50
+ include Jschematic::Element
51
+
52
+ def accepts?(addr_with_cidr)
53
+ addr, cidr = addr_with_cidr.split("/")
54
+ return false unless cidr && (1..32).include?(cidr.to_i)
55
+ Ip.new("ip-address").accepts?(addr)
56
+ end
57
+ end
58
+
47
59
  class NullFormat
48
60
  include Jschematic::Element
49
61
 
@@ -1,22 +1,15 @@
1
- require 'jschematic/element'
1
+ require 'jschematic/attributes/properties'
2
2
 
3
3
  module Jschematic
4
4
  module Attributes
5
- class PatternProperties
6
- include Jschematic::Element
5
+ class PatternProperties < Properties
7
6
 
8
- def initialize(schema)
9
- @schema = schema
10
- end
7
+ private
11
8
 
12
- def accepts?(instance)
13
- instance.all? do |property, value|
14
- if match = @schema.find{ |re, schema| property =~ Regexp.new(re) }
15
- Schema.new(match[1]).accepts?(value)
16
- else
17
- false
18
- end
19
- end || fail_validation!(@schema, instance)
9
+ def find_instance_for(instance, wanted_name)
10
+ instance.find do |property_name, _|
11
+ property_name =~ Regexp.new(wanted_name)
12
+ end
20
13
  end
21
14
  end
22
15
  end
@@ -1,38 +1,52 @@
1
- require 'jschematic/element'
1
+ require 'jschematic/composite'
2
2
 
3
3
  module Jschematic
4
4
  module Attributes
5
5
  class Properties
6
- include Jschematic::Element
6
+ include Jschematic::Composite
7
7
 
8
8
  def initialize(properties)
9
- @schemas = properties.inject({}) do |schemas, (name, schema)|
10
- schemas[name] = Schema.new(schema)
11
- schemas[name].parent = self
12
- schemas
9
+ properties.each_pair do |name, raw_schema|
10
+ schema = Schema.with_name(raw_schema, name)
11
+ add_child(schema)
13
12
  end
14
13
  end
15
14
 
16
15
  def accepts?(instance)
17
- @schemas.all? do |name, schema|
18
- value = instance.fetch(name) do |missing|
19
- return true unless schema.required?
20
- fail_validation!(missing, nil) unless schema.default
21
- schema.default
16
+ children.all? do |child|
17
+ match = find_instance_for(instance, child.name)
18
+
19
+ if match
20
+ value = match.last
21
+ else
22
+ value = nil
23
+ end
24
+
25
+ if !value and child.default
26
+ value = child.default
22
27
  end
23
- schema.accepts?(value) || fail_validation!(name, value)
24
- end
25
- end
26
28
 
27
- def each(&block)
28
- @schemas.values.each do |schema|
29
- block.call(schema)
29
+ if !value and child.required?
30
+ fail_validation!("#{child.name} is required", nil)
31
+ elsif !value
32
+ true
33
+ else
34
+ child.accepts?(value) || fail_validation!(child.name, value)
35
+ end
30
36
  end
31
37
  end
32
38
 
33
39
  def id
34
40
  @parent.id
35
41
  end
42
+
43
+ private
44
+
45
+ def find_instance_for(instance, wanted_name)
46
+ instance.find do |property_name, _|
47
+ property_name == wanted_name
48
+ end
49
+ end
36
50
  end
37
51
  end
38
52
  end
@@ -0,0 +1,22 @@
1
+ require 'jschematic/element'
2
+
3
+ module Jschematic
4
+ module Composite
5
+ include Enumerable
6
+ include Jschematic::Element
7
+
8
+ def children
9
+ @children ||= []
10
+ end
11
+
12
+ def add_child(child)
13
+ child.parent = self
14
+ children << child
15
+ end
16
+
17
+ def each(&block)
18
+ block.call(self)
19
+ children.each{ |child| child.each(&block) }
20
+ end
21
+ end
22
+ end
@@ -1,16 +1,24 @@
1
1
  require 'addressable/uri'
2
2
 
3
3
  require 'jschematic/errors'
4
- require 'jschematic/element'
4
+ require 'jschematic/composite'
5
5
  require 'jschematic/attributes'
6
6
 
7
7
  module Jschematic
8
8
  class Schema
9
- include Enumerable
10
- include Jschematic::Element
9
+ include Jschematic::Composite
10
+
11
+ # TODO: Spec
12
+ def self.with_name(raw_schema, name)
13
+ schema = new(raw_schema)
14
+ schema.name = name
15
+ schema
16
+ end
11
17
 
12
18
  attr_reader :default, :title, :description, :id
13
- attr_writer :parent
19
+
20
+ attr_accessor :name
21
+ attr_writer :parent
14
22
 
15
23
  def initialize(raw_schema)
16
24
  @raw_schema = raw_schema.dup || {}
@@ -20,13 +28,10 @@ module Jschematic
20
28
  @description = @raw_schema.delete("description") || ""
21
29
  @id = Addressable::URI.parse(@raw_schema.delete("id") || "")
22
30
 
23
- @attributes = []
24
-
25
31
  @raw_schema.each_pair do |attribute, value|
26
32
  begin
27
33
  attribute = Attributes[attribute].new(value){ |dep| @raw_schema[dep] }
28
- attribute.parent = self
29
- @attributes << attribute
34
+ add_child(attribute)
30
35
  rescue NameError => e
31
36
  # Not finding an attribute is not necessarily an error, but this is
32
37
  # obviously not the right way to handle it. Need to find a better way to
@@ -39,16 +44,11 @@ module Jschematic
39
44
  end
40
45
 
41
46
  def accepts?(instance)
42
- @attributes.all?{ |child| child.accepts?(add_default(instance)) }
47
+ children.all?{ |child| child.accepts?(add_default(instance)) }
43
48
  end
44
49
 
45
50
  def required?
46
- @attributes.any?{ |child| child.required? }
47
- end
48
-
49
- def each(&block)
50
- block.call(self)
51
- @attributes.each{ |child| child.each(&block) }
51
+ children.any?{ |child| child.required? }
52
52
  end
53
53
 
54
54
  def id
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 1
9
- version: 0.0.1
8
+ - 2
9
+ version: 0.0.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Mike Sassak
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-02-21 00:00:00 -06:00
17
+ date: 2011-02-22 00:00:00 -06:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -83,6 +83,7 @@ files:
83
83
  - .rvmrc
84
84
  - Gemfile
85
85
  - Gemfile.lock
86
+ - History.txt
86
87
  - LICENSE
87
88
  - README.md
88
89
  - Rakefile
@@ -125,6 +126,7 @@ files:
125
126
  - lib/jschematic/attributes/required.rb
126
127
  - lib/jschematic/attributes/type.rb
127
128
  - lib/jschematic/attributes/unique_items.rb
129
+ - lib/jschematic/composite.rb
128
130
  - lib/jschematic/element.rb
129
131
  - lib/jschematic/errors.rb
130
132
  - lib/jschematic/schema.rb
@@ -170,7 +172,7 @@ rubyforge_project:
170
172
  rubygems_version: 1.3.7
171
173
  signing_key:
172
174
  specification_version: 3
173
- summary: jschematic 0.0.1
175
+ summary: jschematic 0.0.2
174
176
  test_files:
175
177
  - features/default.feature
176
178
  - features/dependencies.feature