sinatra-schema 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
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