jschematic 0.0.1 → 0.0.2

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.
@@ -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