sinatra-schema 0.1.2 → 0.1.3
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/README.md +15 -1
- data/lib/sinatra/schema.rb +2 -2
- data/lib/sinatra/schema/definition.rb +10 -2
- data/lib/sinatra/schema/dsl/definitions.rb +12 -2
- data/lib/sinatra/schema/dsl/resources.rb +11 -3
- data/lib/sinatra/schema/json_schema.rb +2 -0
- data/lib/sinatra/schema/reference.rb +15 -5
- data/lib/sinatra/schema/resource.rb +8 -2
- data/lib/sinatra/schema/version.rb +1 -1
- data/spec/definition_spec.rb +17 -0
- data/spec/dsl/definitions_spec.rb +12 -0
- data/spec/dsl/resources_spec.rb +5 -0
- data/spec/json_schema_spec.rb +6 -0
- data/spec/reference_spec.rb +6 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 68898f14935c5a727937d1eec3921da16fab59fc
|
4
|
+
data.tar.gz: 148c841cfeb602cb252d13827a621938997b9298
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6a43e4d2e18ee81dbb18467881a402782953aa54937cd6dfb6a28c61e54822f63b24d876df3645af58b57fb747ea2bc361b7a448b4eb92ebf733eb5725428563
|
7
|
+
data.tar.gz: 8c2e3ea36d035a7c82dd01f26c62eaae3cefd779bdf0c5e8d861e7b5a909635354b515255af1baaf5213182d84916f7292c5b67f692aae400ef34c8d0d13d50c
|
data/README.md
CHANGED
@@ -58,10 +58,24 @@ end
|
|
58
58
|
|
59
59
|
resource("/albums") do |res|
|
60
60
|
res.property.text :name, description: "Album name"
|
61
|
-
res.property.ref :artist_name, "artists/name"
|
61
|
+
res.property.ref :artist_name, to: "artists/name"
|
62
62
|
end
|
63
63
|
```
|
64
64
|
|
65
|
+
You can also customize attributes on the reference so that they're different from the original property. For instance:
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
resource("/artists") do |res|
|
69
|
+
res.property.text :name, description: "Artist name"
|
70
|
+
|
71
|
+
res.patch do |link|
|
72
|
+
link.property.ref :name, optional: true
|
73
|
+
end
|
74
|
+
end
|
75
|
+
```
|
76
|
+
|
77
|
+
In this case the artist name has to be serialized by every endpoint on the resource, but doesn't have to be informed by every request to `PATCH` the resource.
|
78
|
+
|
65
79
|
### Nested properties
|
66
80
|
|
67
81
|
These are also casted and validated as you'd expect:
|
data/lib/sinatra/schema.rb
CHANGED
@@ -22,11 +22,15 @@ module Sinatra
|
|
22
22
|
Time.parse(value.to_s)
|
23
23
|
when "email", "string", "uuid"
|
24
24
|
value.to_s
|
25
|
+
when "integer"
|
26
|
+
value.to_i
|
27
|
+
when "object"
|
28
|
+
value
|
25
29
|
end
|
26
30
|
end
|
27
31
|
|
28
|
-
def valid?(value)
|
29
|
-
return true if value.nil? &&
|
32
|
+
def valid?(value, skip_nils=optional)
|
33
|
+
return true if value.nil? && skip_nils
|
30
34
|
|
31
35
|
case type
|
32
36
|
when "boolean"
|
@@ -35,6 +39,10 @@ module Sinatra
|
|
35
39
|
value.to_s =~ /^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-2][0-9]:[0-5][0-9]:[0-5][0-9](\.[0-9]+)?(Z|[\-+][0-9]{2}:[0-5][0-9])$/
|
36
40
|
when "email"
|
37
41
|
value.to_s =~ /\A[^@\s]+@([^@\s]+\.)+[^@\s]+\z/
|
42
|
+
when "integer"
|
43
|
+
value.to_s =~ /\A\d*\z/
|
44
|
+
when "object"
|
45
|
+
value.is_a?(Hash)
|
38
46
|
when "string"
|
39
47
|
value.is_a?(String)
|
40
48
|
when "uuid"
|
@@ -25,9 +25,19 @@ module Sinatra
|
|
25
25
|
add Definition.new(options)
|
26
26
|
end
|
27
27
|
|
28
|
+
def int(id, options={})
|
29
|
+
options.merge!(id: id, type: "integer")
|
30
|
+
add Definition.new(options)
|
31
|
+
end
|
32
|
+
|
33
|
+
def object(id, options={})
|
34
|
+
options.merge!(id: id, type: "object")
|
35
|
+
add Definition.new(options)
|
36
|
+
end
|
37
|
+
|
28
38
|
# support references to other properties that are lazily evaluated
|
29
|
-
def ref(id,
|
30
|
-
add Reference.new(resource, id,
|
39
|
+
def ref(id, options={})
|
40
|
+
add Reference.new(resource, id, options)
|
31
41
|
end
|
32
42
|
|
33
43
|
def text(id, options={})
|
@@ -4,9 +4,13 @@ module Sinatra
|
|
4
4
|
class Resources
|
5
5
|
attr_accessor :app, :resource
|
6
6
|
|
7
|
-
def initialize(app,
|
8
|
-
@app
|
9
|
-
|
7
|
+
def initialize(app, path_or_id)
|
8
|
+
@app = app
|
9
|
+
if path_or_id.is_a?(Symbol)
|
10
|
+
@resource = Resource.new(id: path_or_id)
|
11
|
+
else
|
12
|
+
@resource = Resource.new(path: path_or_id)
|
13
|
+
end
|
10
14
|
end
|
11
15
|
|
12
16
|
def description(description)
|
@@ -17,6 +21,10 @@ module Sinatra
|
|
17
21
|
@resource.id = id.to_sym
|
18
22
|
end
|
19
23
|
|
24
|
+
def title(title)
|
25
|
+
@resource.title = title
|
26
|
+
end
|
27
|
+
|
20
28
|
def property
|
21
29
|
DSL::Definitions.new(resource, [resource.defs, resource.properties])
|
22
30
|
end
|
@@ -1,20 +1,25 @@
|
|
1
1
|
module Sinatra
|
2
2
|
module Schema
|
3
3
|
class Reference
|
4
|
-
attr_accessor :id, :ref_spec, :referenced_def, :resource
|
4
|
+
attr_accessor :id, :options, :ref_spec, :referenced_def, :resource
|
5
5
|
|
6
6
|
# helper to lazily delegate method to the referenced definition
|
7
7
|
def self.delegate(attribute)
|
8
8
|
define_method(attribute) do |*args|
|
9
|
+
# support overriding attributes. example: referenced
|
10
|
+
# definition is optional, but parameter is not
|
11
|
+
return options[attribute] if options.has_key?(attribute)
|
12
|
+
|
9
13
|
resolve!
|
10
14
|
referenced_def.send(attribute, *args)
|
11
15
|
end
|
12
16
|
end
|
13
17
|
|
14
|
-
def initialize(resource, id,
|
15
|
-
@id = id
|
16
|
-
@ref_spec = ref_spec || id
|
18
|
+
def initialize(resource, id, options={})
|
17
19
|
@resource = resource
|
20
|
+
@id = id
|
21
|
+
@ref_spec = options[:to] || id
|
22
|
+
@options = options
|
18
23
|
end
|
19
24
|
|
20
25
|
def resolve!
|
@@ -30,7 +35,12 @@ module Sinatra
|
|
30
35
|
delegate :example
|
31
36
|
delegate :optional
|
32
37
|
delegate :type
|
33
|
-
|
38
|
+
|
39
|
+
# redefine to make sure overrides on "optional" are considered
|
40
|
+
def valid?(value)
|
41
|
+
resolve!
|
42
|
+
referenced_def.valid?(value, self.optional)
|
43
|
+
end
|
34
44
|
end
|
35
45
|
end
|
36
46
|
end
|
@@ -4,7 +4,8 @@ module Sinatra
|
|
4
4
|
attr_accessor :id, :path, :title, :defs, :links, :description, :properties
|
5
5
|
|
6
6
|
def initialize(options)
|
7
|
-
@
|
7
|
+
@id = options[:id]
|
8
|
+
@path = (options[:path] || "").chomp("/")
|
8
9
|
@links = []
|
9
10
|
@defs = {}
|
10
11
|
@properties = {}
|
@@ -40,7 +41,12 @@ module Sinatra
|
|
40
41
|
end
|
41
42
|
|
42
43
|
def validate_properties!(received)
|
43
|
-
|
44
|
+
required_properties = properties.map do |k, prop|
|
45
|
+
# ignore nested properties for now, we'll cover these next
|
46
|
+
k unless prop.is_a?(Hash) || prop.optional
|
47
|
+
end.compact
|
48
|
+
|
49
|
+
missing = required_properties.map(&:to_s).sort - received.keys.map(&:to_s).sort
|
44
50
|
unless missing.empty?
|
45
51
|
raise BadResponse.new("Missing properties: #{missing}")
|
46
52
|
end
|
data/spec/definition_spec.rb
CHANGED
@@ -26,6 +26,11 @@ describe Sinatra::Schema::Definition do
|
|
26
26
|
assert_equal "UTC", t.zone
|
27
27
|
end
|
28
28
|
|
29
|
+
it "casts integers" do
|
30
|
+
definition.type = "integer"
|
31
|
+
assert_equal 42, definition.cast("42")
|
32
|
+
end
|
33
|
+
|
29
34
|
it "casts text" do
|
30
35
|
definition.type = "string"
|
31
36
|
assert_equal "123", definition.cast(123)
|
@@ -46,6 +51,18 @@ describe Sinatra::Schema::Definition do
|
|
46
51
|
refute definition.valid?("foobar.com")
|
47
52
|
end
|
48
53
|
|
54
|
+
it "validates integers" do
|
55
|
+
definition.type = "integer"
|
56
|
+
assert definition.valid?(42)
|
57
|
+
refute definition.valid?("42omg")
|
58
|
+
end
|
59
|
+
|
60
|
+
it "validates objects" do
|
61
|
+
definition.type = "object"
|
62
|
+
assert definition.valid?(good: true)
|
63
|
+
refute definition.valid?("bad")
|
64
|
+
end
|
65
|
+
|
49
66
|
it "validates text" do
|
50
67
|
definition.type = "string"
|
51
68
|
assert definition.valid?("foo")
|
@@ -23,6 +23,18 @@ describe Sinatra::Schema::DSL::Definitions do
|
|
23
23
|
assert_equal "email", resource.defs[:foobar].type
|
24
24
|
end
|
25
25
|
|
26
|
+
it "adds integer definition to the resource" do
|
27
|
+
dsl.int(:foobar)
|
28
|
+
assert_equal 1, resource.defs.size
|
29
|
+
assert_equal "integer", resource.defs[:foobar].type
|
30
|
+
end
|
31
|
+
|
32
|
+
it "adds object definition to the resource" do
|
33
|
+
dsl.object(:foobar)
|
34
|
+
assert_equal 1, resource.defs.size
|
35
|
+
assert_equal "object", resource.defs[:foobar].type
|
36
|
+
end
|
37
|
+
|
26
38
|
it "adds references" do
|
27
39
|
dsl.ref(:another_property)
|
28
40
|
assert_equal 1, resource.defs.size
|
data/spec/dsl/resources_spec.rb
CHANGED
@@ -9,6 +9,11 @@ describe Sinatra::Schema::DSL::Resources do
|
|
9
9
|
assert_equal "This is a foobar", dsl.resource.description
|
10
10
|
end
|
11
11
|
|
12
|
+
it "sets the resource title" do
|
13
|
+
dsl.title("Foobar")
|
14
|
+
assert_equal "Foobar", dsl.resource.title
|
15
|
+
end
|
16
|
+
|
12
17
|
it "sets the id casting to symbol" do
|
13
18
|
dsl.id("account")
|
14
19
|
assert_equal :account, dsl.resource.id
|
data/spec/json_schema_spec.rb
CHANGED
@@ -40,6 +40,12 @@ describe Sinatra::Schema::JsonSchema do
|
|
40
40
|
assert_equal "email", schema[:format]
|
41
41
|
end
|
42
42
|
|
43
|
+
it "handles the integer format" do
|
44
|
+
definition.type = "integer"
|
45
|
+
schema = json_schema.dump_definition(definition)
|
46
|
+
assert_equal "integer", schema[:type]
|
47
|
+
end
|
48
|
+
|
43
49
|
it "handles the uuid format" do
|
44
50
|
definition.type = "uuid"
|
45
51
|
schema = json_schema.dump_definition(definition)
|
data/spec/reference_spec.rb
CHANGED
@@ -2,7 +2,7 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe Sinatra::Schema::Reference do
|
4
4
|
let(:resource) { Sinatra::Schema::Root.instance.resources[:accounts] }
|
5
|
-
let(:ref) { described_class.new(resource, :
|
5
|
+
let(:ref) { described_class.new(resource, :email) }
|
6
6
|
let(:definition) { resource.defs[:email] }
|
7
7
|
|
8
8
|
describe "#resolve!" do
|
@@ -49,5 +49,10 @@ describe Sinatra::Schema::Reference do
|
|
49
49
|
it "#valid?" do
|
50
50
|
assert_equal definition.valid?("foo"), ref.valid?("foo")
|
51
51
|
end
|
52
|
+
|
53
|
+
it "supports overriding delegated methods" do
|
54
|
+
ref.options[:description] = "diff"
|
55
|
+
assert_equal "diff", ref.description
|
56
|
+
end
|
52
57
|
end
|
53
58
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sinatra-schema
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pedro Belo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-01-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: multi_json
|