jimmy 0.1.0 → 0.1.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.
- checksums.yaml +4 -4
- data/jimmy.gemspec +2 -0
- data/lib/jimmy.rb +1 -0
- data/lib/jimmy/combination.rb +2 -2
- data/lib/jimmy/domain.rb +64 -17
- data/lib/jimmy/schema.rb +19 -15
- data/lib/jimmy/schema_creation.rb +3 -1
- data/lib/jimmy/schema_type.rb +8 -4
- data/lib/jimmy/schema_types.rb +2 -2
- data/lib/jimmy/schema_types/array.rb +3 -3
- data/lib/jimmy/schema_types/number.rb +1 -1
- data/lib/jimmy/schema_types/object.rb +2 -2
- data/lib/jimmy/schema_types/string.rb +11 -2
- data/lib/jimmy/validation_error.rb +20 -0
- data/lib/jimmy/version.rb +1 -1
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cc78f64835960e1b8d8724bee79adc324f710bb7
|
4
|
+
data.tar.gz: 647dab7d9050d3ec4642b55a2cbc2211bfac1ab9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d8f71fc6b11b45bca65a0f599ef0cfa161d43d0c93e208fa47ec42b840c9584a76a7f358b4063e3901bcc51e65c3b8db948e86d3b336363ec87be098db6cdc26
|
7
|
+
data.tar.gz: c11234863a1c7f3ccc8180c3e4f55b9d88844c648f34efa06aef0d30a31869aae7c21a345a1fcd0df7a0c3463cd71880f09863ce18cc4460dc35c0e0caafa46c
|
data/jimmy.gemspec
CHANGED
@@ -19,6 +19,8 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ['lib']
|
20
20
|
spec.license = 'Apache License, Version 2.0'
|
21
21
|
|
22
|
+
spec.add_dependency 'json-schema', '~> 2.5'
|
23
|
+
|
22
24
|
spec.add_development_dependency 'bundler', '~> 1.9'
|
23
25
|
spec.add_development_dependency 'rake', '~> 10.0'
|
24
26
|
spec.add_development_dependency 'rspec', '~> 3.2'
|
data/lib/jimmy.rb
CHANGED
data/lib/jimmy/combination.rb
CHANGED
data/lib/jimmy/domain.rb
CHANGED
@@ -1,47 +1,94 @@
|
|
1
1
|
require 'uri'
|
2
2
|
require 'pathname'
|
3
|
+
require 'json'
|
4
|
+
require 'json-schema'
|
3
5
|
|
4
6
|
require_relative 'schema_creation'
|
5
7
|
|
6
8
|
module Jimmy
|
7
9
|
class Domain
|
8
10
|
|
9
|
-
attr_reader :root, :types
|
11
|
+
attr_reader :root, :types, :partials
|
10
12
|
|
11
13
|
def initialize(root)
|
12
|
-
@root
|
13
|
-
@schemas
|
14
|
-
@types
|
14
|
+
@root = URI(root)
|
15
|
+
@schemas = {}
|
16
|
+
@types = {}
|
17
|
+
@partials = {}
|
18
|
+
@import_paths = []
|
15
19
|
end
|
16
20
|
|
17
21
|
def domain
|
18
22
|
self
|
19
23
|
end
|
20
24
|
|
21
|
-
def
|
25
|
+
def import(path)
|
22
26
|
path = Pathname(path) unless path.is_a? Pathname
|
23
|
-
@
|
24
|
-
|
27
|
+
@import_paths << path unless @import_paths.include? path
|
28
|
+
|
29
|
+
glob path, only: 'types' do |name, schema|
|
30
|
+
@types[name.to_sym] = schema
|
31
|
+
end
|
32
|
+
|
33
|
+
glob path, only: 'partials' do |name|
|
34
|
+
partial_path = path + 'partials' + "#{name}.rb"
|
35
|
+
@partials[name] = [partial_path.read, partial_path.to_s]
|
36
|
+
end
|
37
|
+
|
38
|
+
glob path, ignore: %r`^(types|partials)/` do |name, schema|
|
39
|
+
@schemas[name] = schema
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def autoload_type(name)
|
44
|
+
# TODO: protect from circular dependency
|
45
|
+
return if types.key? name
|
46
|
+
@import_paths.each do |import_path|
|
47
|
+
path = import_path + "types/#{name}.rb"
|
48
|
+
if path.file?
|
49
|
+
@types[name] = load_schema_from_path(path, name)
|
50
|
+
return true
|
51
|
+
end
|
52
|
+
end
|
53
|
+
false
|
25
54
|
end
|
26
55
|
|
27
56
|
def [](schema_name)
|
28
57
|
@schemas[schema_name.to_s]
|
29
58
|
end
|
30
59
|
|
60
|
+
def export(path = nil)
|
61
|
+
path = Pathname(path) if path.is_a? String
|
62
|
+
raise 'Please specify an export directory' unless path.is_a?(Pathname) && (path.directory? || !path.exist?)
|
63
|
+
path.mkpath
|
64
|
+
@schemas.each { |name, schema| export_schema schema, path + "#{name.to_s}.json" }
|
65
|
+
@types.each { |name, schema| export_schema schema, path + 'types' + "#{name.to_s}.json" }
|
66
|
+
end
|
67
|
+
|
31
68
|
private
|
32
69
|
|
33
|
-
def
|
34
|
-
|
35
|
-
Dir[
|
70
|
+
def glob(base_path, only: '.', ignore: nil, &block)
|
71
|
+
lookup_path = base_path + only
|
72
|
+
Dir[lookup_path + '**/*.rb'].each do |full_path|
|
36
73
|
full_path = Pathname(full_path)
|
37
|
-
relative_path = full_path.relative_path_from(
|
38
|
-
next if
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
74
|
+
relative_path = full_path.relative_path_from(lookup_path)
|
75
|
+
next if ignore === relative_path.to_s
|
76
|
+
args = [relative_path.to_s[0..-4]]
|
77
|
+
args << load_schema_from_path(full_path, full_path.relative_path_from(base_path).to_s[0..-4]) if block.arity == 2
|
78
|
+
yield *args
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def load_schema_from_path(path, name)
|
83
|
+
instance_eval(path.read, path.to_s).schema.tap do |schema|
|
84
|
+
schema.name = name.to_s
|
85
|
+
JSON::Validator.add_schema JSON::Schema.new(schema.to_h, nil)
|
43
86
|
end
|
44
|
-
|
87
|
+
end
|
88
|
+
|
89
|
+
def export_schema(schema, target_path)
|
90
|
+
target_path.parent.mkpath
|
91
|
+
target_path.write JSON.pretty_generate(schema.to_h)
|
45
92
|
end
|
46
93
|
|
47
94
|
SchemaCreation.apply_to self
|
data/lib/jimmy/schema.rb
CHANGED
@@ -5,13 +5,7 @@ module Jimmy
|
|
5
5
|
attr_accessor :name
|
6
6
|
|
7
7
|
@argument_handlers = Hash.new { |hash, key| hash[key] = {} }
|
8
|
-
|
9
|
-
def self.create(*args, &block)
|
10
|
-
new(*args).tap do |schema|
|
11
|
-
schema.dsl.evaluate block if block
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
8
|
+
|
15
9
|
def self.set_argument_handler(schema_class, arg_class, handler)
|
16
10
|
@argument_handlers[schema_class][arg_class] = handler
|
17
11
|
end
|
@@ -26,28 +20,37 @@ module Jimmy
|
|
26
20
|
result && result.last
|
27
21
|
end
|
28
22
|
|
29
|
-
def
|
30
|
-
|
23
|
+
def compile
|
24
|
+
compiler = nil
|
31
25
|
schema_class = SchemaTypes[type]
|
32
26
|
until schema_class == SchemaType do
|
33
|
-
|
27
|
+
compiler ||= SchemaTypes.compilers[schema_class]
|
34
28
|
schema_class = schema_class.superclass
|
35
29
|
end
|
36
30
|
{'type' => type.to_s}.tap do |hash|
|
37
|
-
dsl.evaluate
|
31
|
+
dsl.evaluate compiler, hash if compiler
|
38
32
|
end
|
39
33
|
end
|
40
34
|
|
35
|
+
def url
|
36
|
+
"#{domain.root}/#{name}.json#"
|
37
|
+
end
|
38
|
+
|
41
39
|
def to_h
|
42
|
-
{}.tap do |hash|
|
43
|
-
hash['
|
44
|
-
hash.merge!
|
40
|
+
{'$schema' => 'http://json-schema.org/draft-04/schema#'}.tap do |hash|
|
41
|
+
hash['id'] = url if name
|
42
|
+
hash.merge! compile
|
45
43
|
end
|
46
44
|
end
|
47
45
|
|
46
|
+
def validate(data)
|
47
|
+
errors = JSON::Validator.fully_validate(JSON::Validator.schema_for_uri(url).schema, data, errors_as_objects: true)
|
48
|
+
raise ValidationError.new(self, data, errors) unless errors.empty?
|
49
|
+
end
|
50
|
+
|
48
51
|
private
|
49
52
|
|
50
|
-
def initialize(type, domain, *args)
|
53
|
+
def initialize(type, domain, *args, &block)
|
51
54
|
@attrs = {}
|
52
55
|
@type = type
|
53
56
|
@domain = domain
|
@@ -64,6 +67,7 @@ module Jimmy
|
|
64
67
|
dsl.evaluate handler, arg
|
65
68
|
end
|
66
69
|
end
|
70
|
+
dsl.evaluate block if block
|
67
71
|
end
|
68
72
|
|
69
73
|
end
|
@@ -32,13 +32,15 @@ module Jimmy
|
|
32
32
|
handler = SchemaCreation.handlers[self.class]
|
33
33
|
self.class.__send__ :define_method, method do |*inner_args, &inner_block|
|
34
34
|
handler_args = handler && inner_args.shift(handler.arity - 1)
|
35
|
-
schema = Schema.
|
35
|
+
schema = Schema.new(method, domain, *inner_args, &inner_block)
|
36
36
|
instance_exec schema, *handler_args, &handler if handler
|
37
37
|
schema.dsl
|
38
38
|
end
|
39
39
|
return __send__ method, *args, &block
|
40
40
|
end
|
41
41
|
|
42
|
+
domain.autoload_type method
|
43
|
+
|
42
44
|
if domain.types.key? method
|
43
45
|
return instance_exec method, *args, &SchemaCreation.handlers[self.class]
|
44
46
|
end
|
data/lib/jimmy/schema_type.rb
CHANGED
@@ -27,8 +27,8 @@ module Jimmy
|
|
27
27
|
SchemaTypes.nested_handlers[self] = handler
|
28
28
|
end
|
29
29
|
|
30
|
-
def
|
31
|
-
SchemaTypes.
|
30
|
+
def compile(&handler)
|
31
|
+
SchemaTypes.compilers[self] = handler
|
32
32
|
end
|
33
33
|
|
34
34
|
end
|
@@ -53,8 +53,12 @@ module Jimmy
|
|
53
53
|
included_args.map { |arg| [arg.to_s.gsub(/_([a-z])/) { $1.upcase }, attrs[arg]] }.to_h
|
54
54
|
end
|
55
55
|
|
56
|
-
def
|
57
|
-
schema.is_a?(Symbol) ? {'$ref' => "/types/#{schema}#"} : schema.
|
56
|
+
def compile_schema(schema)
|
57
|
+
schema.is_a?(Symbol) ? {'$ref' => "/types/#{schema}.json#"} : schema.compile
|
58
|
+
end
|
59
|
+
|
60
|
+
def include(*partial_names)
|
61
|
+
partial_names.each { |name| instance_eval *domain.partials[name.to_s] }
|
58
62
|
end
|
59
63
|
|
60
64
|
end
|
data/lib/jimmy/schema_types.rb
CHANGED
@@ -9,14 +9,14 @@ module Jimmy
|
|
9
9
|
@types = {}
|
10
10
|
@dsls = {}
|
11
11
|
@nested_handlers = {}
|
12
|
-
@
|
12
|
+
@compilers = {}
|
13
13
|
|
14
14
|
class << self
|
15
15
|
extend Forwardable
|
16
16
|
|
17
17
|
delegate %i[each keys values key?] => :@types
|
18
18
|
|
19
|
-
attr_reader :dsls, :nested_handlers, :
|
19
|
+
attr_reader :dsls, :nested_handlers, :compilers
|
20
20
|
|
21
21
|
def [](type_name)
|
22
22
|
@types[type_name]
|
@@ -15,13 +15,13 @@ module Jimmy
|
|
15
15
|
(attrs[:items] ||= []) << schema
|
16
16
|
end
|
17
17
|
|
18
|
-
|
18
|
+
compile do |hash|
|
19
19
|
hash.merge! camelize_attrs(%i[min_items max_items])
|
20
20
|
items = attrs[:items] || []
|
21
21
|
if items.length > 1
|
22
|
-
hash['items'] = {'anyOf' => items.map { |i|
|
22
|
+
hash['items'] = {'anyOf' => items.map { |i| compile_schema i }}
|
23
23
|
elsif items.length == 1
|
24
|
-
hash['items'] =
|
24
|
+
hash['items'] = compile_schema(items.first)
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
@@ -23,7 +23,7 @@ module Jimmy
|
|
23
23
|
(attrs[:properties] ||= {})[property_name] = schema
|
24
24
|
end
|
25
25
|
|
26
|
-
|
26
|
+
compile do |hash|
|
27
27
|
(attrs[:properties] || {}).each do |key, value|
|
28
28
|
collection, key =
|
29
29
|
if key.is_a? Regexp
|
@@ -32,7 +32,7 @@ module Jimmy
|
|
32
32
|
['properties', key.to_s]
|
33
33
|
end
|
34
34
|
hash[collection] ||= {}
|
35
|
-
hash[collection][key] =
|
35
|
+
hash[collection][key] = compile_schema(value)
|
36
36
|
end
|
37
37
|
hash['required'] = (attrs[:required] || []).to_a
|
38
38
|
hash['additionalProperties'] = !!attrs[:additional_properties]
|
@@ -6,11 +6,20 @@ module Jimmy
|
|
6
6
|
trait :max_length
|
7
7
|
trait(:pattern) { |regex| attrs[:pattern] = regex.is_a?(Regexp) ? regex.inspect.gsub(%r`^/|/[a-z]*$`, '') : regex }
|
8
8
|
trait(Regexp) { |regex| pattern regex }
|
9
|
-
trait
|
9
|
+
trait Range do |value|
|
10
|
+
variation = value.exclude_end? ? 1 : 0
|
11
|
+
if value.first < value.last
|
12
|
+
attrs[:min_length] = value.first
|
13
|
+
attrs[:max_length] = value.last - variation
|
14
|
+
else
|
15
|
+
attrs[:max_length] = value.first
|
16
|
+
attrs[:min_length] = value.last + variation
|
17
|
+
end
|
18
|
+
end
|
10
19
|
trait(Fixnum) { |value| min_length value; max_length value }
|
11
20
|
trait(Array) { |value| attrs[:enum] = value.map(&:to_s) }
|
12
21
|
|
13
|
-
|
22
|
+
compile do |hash|
|
14
23
|
hash.merge! camelize_attrs(%i[min_length max_length pattern enum])
|
15
24
|
end
|
16
25
|
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
module Jimmy
|
4
|
+
class ValidationError < StandardError
|
5
|
+
|
6
|
+
attr_reader :schema, :data, :errors
|
7
|
+
|
8
|
+
def initialize(schema, data, errors)
|
9
|
+
@schema = schema
|
10
|
+
@data = data
|
11
|
+
@errors = errors.map do |info|
|
12
|
+
OpenStruct.new(
|
13
|
+
property: info[:fragment][2..-1],
|
14
|
+
message: info[:message].gsub(/ in schema \S+$/, ''),
|
15
|
+
aspect: info[:failed_attribute]
|
16
|
+
)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/jimmy/version.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jimmy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Neil E. Pearson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-07-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: json-schema
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.5'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.5'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: bundler
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -81,6 +95,7 @@ files:
|
|
81
95
|
- lib/jimmy/schema_types/object.rb
|
82
96
|
- lib/jimmy/schema_types/string.rb
|
83
97
|
- lib/jimmy/symbol_array.rb
|
98
|
+
- lib/jimmy/validation_error.rb
|
84
99
|
- lib/jimmy/version.rb
|
85
100
|
homepage: https://github.com/orionvm/jimmy
|
86
101
|
licenses:
|