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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 603462c6a4aa1a4d10f74c16f6f06572a41e7b20
4
- data.tar.gz: 2dba7d6115b90f6bf2b9fc2b3da650b582aea859
3
+ metadata.gz: 68898f14935c5a727937d1eec3921da16fab59fc
4
+ data.tar.gz: 148c841cfeb602cb252d13827a621938997b9298
5
5
  SHA512:
6
- metadata.gz: 8defef282e9e5912c0ca54d19e94acaca55f426a0dcb8168f97cbc93be76326bdccf420bdfdabd2b5c75b078ac8b9aa9194b28c3487ce660c47017d2f6f13fbd
7
- data.tar.gz: 7acf6b4143b1d239bb29ef7df0dc035037b95694e6fb07efd295c94a0db0893166558664a593cebcbb6a09b02862b0e1ddb32df528bb41e59c30c3637274be25
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:
@@ -41,8 +41,8 @@ module Sinatra
41
41
  Root.instance
42
42
  end
43
43
 
44
- def resource(path)
45
- spec = DSL::Resources.new(self, path)
44
+ def resource(path_or_id)
45
+ spec = DSL::Resources.new(self, path_or_id)
46
46
  yield(spec)
47
47
  schema_root.add_resource(spec.resource)
48
48
  end
@@ -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? && optional
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, ref_to=nil)
30
- add Reference.new(resource, id, ref_to)
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, path)
8
- @app = app
9
- @resource = Resource.new(path: path)
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
@@ -62,6 +62,8 @@ module Sinatra
62
62
  ["string", "date-time"]
63
63
  when "email"
64
64
  ["string", "email"]
65
+ when "integer"
66
+ "integer"
65
67
  when "string"
66
68
  "string"
67
69
  when "uuid"
@@ -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, ref_spec=nil)
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
- delegate :valid?
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
- @path = options.fetch(:path).chomp("/")
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
- missing = properties.keys.map(&:to_s).sort - received.keys.map(&:to_s).sort
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
@@ -1,5 +1,5 @@
1
1
  module Sinatra
2
2
  module Schema
3
- VERSION = "0.1.2"
3
+ VERSION = "0.1.3"
4
4
  end
5
5
  end
@@ -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
@@ -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
@@ -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)
@@ -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, :foo, :email) }
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.2
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: 2014-12-18 00:00:00.000000000 Z
11
+ date: 2015-01-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: multi_json