jsonapi-deserializable 0.1.1.beta2 → 0.1.1.beta3

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: 93ceb39a5f3d032a99748170ac818e096e691d05
4
- data.tar.gz: adfdd698f25de948e225c87087f850376d900f09
3
+ metadata.gz: f3004871b4ea0f17caaeab2c1f000c632337c486
4
+ data.tar.gz: 4eb06414674e45c45fc3d276ffa966bc97313ae7
5
5
  SHA512:
6
- metadata.gz: 52f05a26b475cf2afa912ab7e3e207f4d925c32e58c5ba99edfc8a52685c5c536ecdc8d8e0e7e2d06d44916be0b1af383ba035339c87754824a0988cf93ce48c
7
- data.tar.gz: aa7bfa1f75f1ec8bd00dc69025dffbc7127874b86f946dd1489798837727630df4a15a9410cb8047a26c195b6b6082e185bb3d9770cc586668d9b52f274c5769
6
+ metadata.gz: fdf14b9d40b30ea331a01b10212be3b5582785e45634ab7e49e2d81957a4408af6ce838d05dc27e9d86828a704cef1a2eb23e5331d2c13d4fa131829c6a4c03e
7
+ data.tar.gz: ee5342f0d5444e68773e504353000090dc71117fba3eee3a0af21399c32836085eab9f8076dd70a2cfe54385a85f9140c692007199f12b70ef60315ca76cad64
data/README.md CHANGED
@@ -1,8 +1,11 @@
1
1
  # jsonapi-deserializable
2
- Ruby gem for validating and deserializing [JSON API](http://jsonapi.org)
3
- payloads into custom hashes.
4
- Built upon the [jsonapi-validations](https://github.com/beauby/jsonapi/tree/master/validations)
5
- gem.
2
+ Ruby gem for deserializing [JSON API](http://jsonapi.org) payloads into custom
3
+ hashes.
4
+
5
+ ## Status
6
+
7
+ [![Gem Version](https://badge.fury.io/rb/jsonapi-deserializable.svg)](https://badge.fury.io/rb/jsonapi-deserializable)
8
+ [![Build Status](https://secure.travis-ci.org/beauby/jsonapi-deserializable.svg?branch=master)](http://travis-ci.org/beauby/jsonapi-deserializable?branch=master)
6
9
 
7
10
  ## Installation
8
11
  ```ruby
@@ -26,54 +29,23 @@ require 'jsonapi/deserializable'
26
29
  ```
27
30
 
28
31
  Then, define some resource/relationship classes:
29
- ```ruby
30
- class DeserializableUser < JSONAPI::Deserializable::Resource
31
- # List of required attributes / has_many/has_one relationships.
32
- # This directive is not mandatory. If not declared, no field
33
- # will be required.
34
- required do
35
- id # Optional, require an id for the primary resource.
36
-
37
- type :users # Optional, force a type for the primary resource.
38
- # or, still optional, force a set of allowed types for the primary resource:
39
- types [:users, :superusers] # Optional,
40
-
41
- attribute :name
42
- has_one :sponsor
43
- # or, optionally, spcecify a type for the relationship target:
44
- has_one :sponsor, :users
45
- end
46
-
47
- # List of optional attributes / has_many/has_one relationships.
48
- # This directive is not mandatory. If not declared, all fields
49
- # will be allowed. If declared, all fields that are not within
50
- # eitheroptional or required will be rejected.
51
- optional do
52
- attribute :address
53
- has_many :posts
54
- # or, optionally, specify a set of allowed types for the primary resource:
55
- has_many :posts, [:posts, :blogs]
56
- end
57
-
58
- ## The actual fields of the generated hash.
59
- # `attribute` is a shorthand for `field(key) { @attributes.send(key) }`.
60
- attribute :address
61
-
62
- field :id do
63
- @data.id
64
- end
65
32
 
66
- # `field` is the standard method for defining a key on the result hash.
67
- field :username do
68
- @document.data.attributes.name
69
- end
33
+ ### Resources
70
34
 
71
- field :post_ids do
72
- @relationships.posts.data.map(&:id)
35
+ ```ruby
36
+ class DeserializableCreatePost < JSONAPI::Deserializable::Resource
37
+ type
38
+ attribute :title
39
+ attribute :date { |date| field date: DateTime.parse(date) }
40
+ has_one :author do |rel, id, type|
41
+ field author_id: id
42
+ field author_type: type
73
43
  end
74
-
75
- field :sponsor_id do
76
- @relationships.sponsor.data && @relationships.sponsor.data.id
44
+ has_many :comments do |rel, ids, types|
45
+ field comment_ids: ids
46
+ field comment_types: types.map do |type|
47
+ camelize(singularize(type))
48
+ end
77
49
  end
78
50
  end
79
51
  ```
@@ -82,35 +54,52 @@ Finally, build your hash from the deserializable resource:
82
54
  payload = {
83
55
  'data' => {
84
56
  'id' => '1',
85
- 'type' => 'users',
57
+ 'type' => 'posts',
86
58
  'attributes' => {
87
- 'name' => 'Name',
88
- 'address' => 'Address'
59
+ 'title' => 'Title',
60
+ 'date' => '2016-01-10 02:30:00'
89
61
  },
90
62
  'relationships' => {
91
- 'sponsor' => {
63
+ 'author' => {
92
64
  'data' => { 'type' => 'users', 'id' => '1337' }
93
65
  },
94
- 'posts' => {
66
+ 'comments' => {
95
67
  'data' => [
96
- { 'type' => 'posts', 'id' => '123' },
97
- { 'type' => 'posts', 'id' => '234' },
98
- { 'type' => 'posts', 'id' => '345' }
68
+ { 'type' => 'comments', 'id' => '123' },
69
+ { 'type' => 'comments', 'id' => '234' },
70
+ { 'type' => 'comments', 'id' => '345' }
99
71
  ]
100
72
  }
101
73
  }
102
74
  }
103
75
  }
104
76
 
105
- DeserializableUser.new(payload).to_h
77
+ DeserializableCreateUser.(payload)
106
78
  # => {
107
- # username: 'Name',
108
- # address: 'Address',
109
- # sponsor_id: '1337',
110
- # post_ids: ['123', '234', '345']
79
+ # id: '1',
80
+ # title: 'Title',
81
+ # date: #<DateTime: 2016-01-10T02:30:00+00:00 ((2457398j,9000s,0n),+0s,2299161j)>,
82
+ # author_id: '1337',
83
+ # author_type: 'users',
84
+ # comment_ids: ['123', '234', '345']
85
+ # comment_types: ['Comment', 'Comment', 'Comment']
111
86
  # }
112
87
  ```
113
88
 
89
+ ### Relationships
90
+
91
+ ```
92
+ class DeserializablePostComments < JSONAPI::Deserializable::Relationship
93
+ has_many do |rel, ids, types|
94
+ field comment_ids: ids
95
+ field comment_types: types.map do |ri|
96
+ camelize(singularize(type))
97
+ end
98
+ field comments_meta: rel['meta']
99
+ end
100
+ end
101
+ ```
102
+
114
103
  ## License
115
104
 
116
105
  jsonapi-deserializable is released under the [MIT License](http://www.opensource.org/licenses/MIT).
@@ -1,3 +1,2 @@
1
- require 'jsonapi/deserializable/exceptions'
2
1
  require 'jsonapi/deserializable/relationship'
3
2
  require 'jsonapi/deserializable/resource'
@@ -1,4 +1,3 @@
1
- require 'jsonapi/deserializable/exceptions'
2
1
  require 'jsonapi/deserializable/relationship_dsl'
3
2
 
4
3
  module JSONAPI
@@ -7,31 +6,45 @@ module JSONAPI
7
6
  include RelationshipDSL
8
7
 
9
8
  class << self
10
- attr_accessor :field_blocks, :validations
9
+ attr_accessor :has_one_block, :has_many_block
11
10
  end
12
11
 
13
- self.field_blocks = {}
14
- self.validations = {}
15
-
16
12
  def self.inherited(klass)
17
- klass.field_blocks = field_blocks.dup
18
- klass.validations = Marshal.load(Marshal.dump(validations))
13
+ klass.has_one_block = has_one_block
14
+ klass.has_many_block = has_many_block
15
+ end
16
+
17
+ def self.call(payload)
18
+ new(payload).to_h
19
19
  end
20
20
 
21
21
  def initialize(payload)
22
- JSONAPI.validate_relationship!(payload, validations)
23
22
  @document = payload
24
23
  @data = payload['data']
24
+ deserialize!
25
25
  end
26
26
 
27
27
  def to_h
28
- return nil if @data.nil?
29
- return @_hash if @_hash
30
- @_hash = {}
31
- self.class.field_blocks.each do |key, block|
32
- @_hash[key] = instance_eval(&block)
28
+ @hash
29
+ end
30
+
31
+ private
32
+
33
+ def deserialize!
34
+ @hash = {}
35
+ if @data.is_a?(Array)
36
+ ids = @data.map { |ri| ri['id'] }
37
+ types = @data.map { |ri| ri['type'] }
38
+ instance_exec(@document, ids, types, &self.class.has_many_block)
39
+ else
40
+ id = @data && @data['id']
41
+ type = @data && @data['type']
42
+ instance_exec(@document, id, type, &self.class.has_one_block)
33
43
  end
34
- @_hash
44
+ end
45
+
46
+ def field(hash)
47
+ @hash.merge!(hash)
35
48
  end
36
49
  end
37
50
  end
@@ -6,24 +6,14 @@ module JSONAPI
6
6
  end
7
7
 
8
8
  module ClassMethods
9
- def has_one
10
- validations[:kind] = :has_one
9
+ def has_one(&block)
10
+ block ||= proc { |rel| field key.to_sym => rel }
11
+ self.has_one_block = block
11
12
  end
12
13
 
13
- def has_many
14
- validations[:kind] = :has_many
15
- end
16
-
17
- def type(value)
18
- (validations[:types] ||= []) << value
19
- end
20
-
21
- def types(values)
22
- (validations[:types] ||= []).concat(values)
23
- end
24
-
25
- def field(key, &block)
26
- field_blocks[key] = block
14
+ def has_many(&block)
15
+ block ||= proc { |rel| field key.to_sym => rel }
16
+ self.has_many_block = block
27
17
  end
28
18
  end
29
19
  end
@@ -1,5 +1,3 @@
1
- require 'jsonapi/validations'
2
- require 'jsonapi/deserializable/exceptions'
3
1
  require 'jsonapi/deserializable/resource_dsl'
4
2
 
5
3
  module JSONAPI
@@ -8,36 +6,104 @@ module JSONAPI
8
6
  include ResourceDSL
9
7
 
10
8
  class << self
11
- attr_accessor :field_blocks, :validations
9
+ attr_accessor :type_block, :id_block
10
+ attr_accessor :attr_blocks
11
+ attr_accessor :has_one_rel_blocks, :has_many_rel_blocks
12
12
  end
13
13
 
14
- self.field_blocks = {}
15
- self.validations = {}
14
+ self.attr_blocks = {}
15
+ self.has_one_rel_blocks = {}
16
+ self.has_many_rel_blocks = {}
16
17
 
17
18
  def self.inherited(klass)
18
19
  super
19
- klass.field_blocks = field_blocks.dup
20
- klass.validations = Marshal.load(Marshal.dump(validations))
20
+ klass.type_block = type_block
21
+ klass.id_block = id_block
22
+ klass.attr_blocks = attr_blocks.dup
23
+ klass.has_one_rel_blocks = has_one_rel_blocks.dup
24
+ klass.has_many_rel_blocks = has_many_rel_blocks.dup
25
+ end
26
+
27
+ def self.call(payload)
28
+ new(payload).to_h
21
29
  end
22
30
 
23
31
  def initialize(payload)
24
- JSONAPI.validate_resource!(payload, self.class.validations)
25
32
  @document = payload
26
33
  @data = @document['data']
27
- @attributes = @data['attributes']
28
- @relationships = @data['relationships']
34
+ @type = @data['type']
35
+ @id = @data['id']
36
+ @attributes = @data['attributes'] || {}
37
+ @relationships = @data['relationships'] || {}
38
+ deserialize!
29
39
  end
30
40
 
31
41
  def to_h
32
- return @_hash if @_hash
42
+ @hash
43
+ end
44
+
45
+ private
46
+
47
+ def deserialize!
48
+ @hash = {}
49
+ deserialize_type!
50
+ deserialize_id!
51
+ deserialize_attrs!
52
+ deserialize_rels!
53
+ end
33
54
 
34
- @_hash = {}
35
- @_hash[:_payload] = @document
36
- self.class.field_blocks.map do |k, v|
37
- @_hash[k] = instance_eval(&v)
55
+ def deserialize_type!
56
+ return unless @type && self.class.type_block
57
+ instance_exec(@type, &self.class.type_block)
58
+ end
59
+
60
+ def deserialize_id!
61
+ return unless @id && self.class.id_block
62
+ instance_exec(@id, &self.class.id_block)
63
+ end
64
+
65
+ def deserialize_attrs!
66
+ self.class.attr_blocks.each do |attr, block|
67
+ next unless @attributes.key?(attr)
68
+ instance_exec(@attributes[attr], &block)
38
69
  end
70
+ end
71
+
72
+ def deserialize_rels!
73
+ deserialize_has_one_rels!
74
+ deserialize_has_many_rels!
75
+ end
76
+
77
+ def deserialize_has_one_rels!
78
+ self.class.has_one_rel_blocks.each do |key, block|
79
+ rel = @relationships[key]
80
+ next unless rel && (rel['data'].nil? || rel['data'].is_a?(Hash))
81
+ deserialize_has_one_rel!(rel, &block)
82
+ end
83
+ end
84
+
85
+ def deserialize_has_one_rel!(rel, &block)
86
+ id = rel['data'] && rel['data']['id']
87
+ type = rel['data'] && rel['data']['type']
88
+ instance_exec(rel, id, type, &block)
89
+ end
90
+
91
+ def deserialize_has_many_rels!
92
+ self.class.has_many_rel_blocks.each do |key, block|
93
+ rel = @relationships[key]
94
+ next unless rel && rel['data'].is_a?(Array)
95
+ deserialize_has_many_rel!(rel, &block)
96
+ end
97
+ end
98
+
99
+ def deserialize_has_many_rel!(rel, &block)
100
+ ids = rel['data'].map { |ri| ri['id'] }
101
+ types = rel['data'].map { |ri| ri['type'] }
102
+ instance_exec(rel, ids, types, &block)
103
+ end
39
104
 
40
- @_hash
105
+ def field(hash)
106
+ @hash.merge!(hash)
41
107
  end
42
108
  end
43
109
  end
@@ -1,5 +1,3 @@
1
- require 'jsonapi/deserializable/validations'
2
-
3
1
  module JSONAPI
4
2
  module Deserializable
5
3
  module ResourceDSL
@@ -8,65 +6,32 @@ module JSONAPI
8
6
  end
9
7
 
10
8
  module ClassMethods
11
- def required(&block)
12
- add_validations!(Validations.new(:required, &block).to_h)
13
- end
14
-
15
- def optional(&block)
16
- add_validations!(Validations.new(:optional, &block).to_h)
17
- end
18
-
19
- def field(key, &block)
20
- field_blocks[key] = block
21
- end
22
-
23
- def id
24
- field(:id) { @data['id'] }
9
+ def type(&block)
10
+ block ||= proc { |type| field type: type }
11
+ self.type_block = block
25
12
  end
26
13
 
27
- def attribute(key, opts = {})
28
- hash_key = (opts[:key] || key).to_s
29
- field(key) { @attributes[hash_key] }
14
+ def id(&block)
15
+ block ||= proc { |id| field id: id }
16
+ self.id_block = block
30
17
  end
31
18
 
32
- def has_many_ids(key, opts = {})
33
- hash_key = (opts[:key] || key).to_s
34
- field(key) do
35
- @relationships[hash_key]['data'].map { |ri| ri['id'] }
19
+ def attribute(key, options = {}, &block)
20
+ unless block
21
+ options[:key] ||= key.to_sym
22
+ block = proc { |attr| field key => attr }
36
23
  end
24
+ attr_blocks[key.to_s] = block
37
25
  end
38
26
 
39
- def has_many_types(key, opts = {})
40
- hash_key = (opts[:key] || key).to_s
41
- field(key) do
42
- @relationships[hash_key]['data'].map { |ri| ri['type'] }
43
- end
44
- end
45
-
46
- def has_one_id(key, opts = {})
47
- hash_key = (opts[:key] || key).to_s
48
- field(key) { @relationships[hash_key]['data']['id'] }
27
+ def has_one(key, &block)
28
+ block ||= proc { |rel| field key.to_sym => rel }
29
+ has_one_rel_blocks[key.to_s] = block
49
30
  end
50
31
 
51
- def has_one_type(key, opts = {})
52
- hash_key = (opts[:key] || key).to_s
53
- field(key) { @relationships[hash_key]['data']['type'] }
54
- end
55
-
56
- private
57
-
58
- def add_validations!(hash)
59
- validations[:permitted] = hash[:permitted] if hash[:permitted]
60
- validations[:required] = hash[:required] if hash[:required]
61
- return unless hash[:types]
62
- validations[:types] ||= {}
63
- if hash[:types][:primary]
64
- validations[:types][:primary] = hash[:types][:primary]
65
- end
66
- return unless hash[:types][:relationships]
67
- validations[:types][:relationships] ||= {}
68
- validations[:types][:relationships]
69
- .merge!(hash[:types][:relationships])
32
+ def has_many(key, &block)
33
+ block ||= proc { |rel| field key.to_sym => rel }
34
+ has_many_rel_blocks[key.to_s] = block
70
35
  end
71
36
  end
72
37
  end
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsonapi-deserializable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1.beta2
4
+ version: 0.1.1.beta3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lucas Hosseini
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-10-02 00:00:00.000000000 Z
11
+ date: 2016-10-25 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: jsonapi-validations
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '0.1'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '0.1'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: rake
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -61,14 +47,11 @@ extra_rdoc_files: []
61
47
  files:
62
48
  - README.md
63
49
  - lib/jsonapi/deserializable.rb
64
- - lib/jsonapi/deserializable/document_validator.rb
65
- - lib/jsonapi/deserializable/exceptions.rb
66
50
  - lib/jsonapi/deserializable/relationship.rb
67
51
  - lib/jsonapi/deserializable/relationship_dsl.rb
68
52
  - lib/jsonapi/deserializable/resource.rb
69
53
  - lib/jsonapi/deserializable/resource/dsl.rb
70
54
  - lib/jsonapi/deserializable/resource_dsl.rb
71
- - lib/jsonapi/deserializable/validations.rb
72
55
  homepage: https://github.com/beauby/jsonapi-deserializable
73
56
  licenses:
74
57
  - MIT
@@ -1,200 +0,0 @@
1
- require 'jsonapi/deserializable/field_list'
2
-
3
- module JSONAPI
4
- module Deserializable
5
- class DocumentValidator
6
- def self.validate!(payload, required_list, optional_list)
7
- new(payload, required_list, optional_list).validate!
8
- end
9
-
10
- def initialize(document, required, optional)
11
- whitelist = {
12
- id: :optional,
13
- types: [],
14
- attributes: {
15
- foo: :required,
16
- bar: :optional
17
- },
18
- relationships: {
19
- foobar: :required,
20
- barfoo: {
21
- required: true,
22
- types: [:baz],
23
- arity: :to_many
24
- }
25
- }
26
- }
27
-
28
-
29
- arities = {
30
- foobar: :to_many,
31
- barfoo: :to_one
32
- }
33
- types = {
34
- primary: [],
35
- relationships: {
36
- foobar: [:baz],
37
- barfoo: [:bazbaz]
38
- }
39
- }
40
- required: true,
41
- types: [:baz],
42
- arity: :to_many
43
- }
44
- }
45
- }
46
- @document = document
47
- @required = required || {}
48
- @optional = optional
49
- @fields = {}
50
- @fields[:primary_id] = true if @required[:primary_id]
51
- primary_types = @required[:primary_types]
52
- @fields[:primary_types] = primary_types if primary_types
53
- @fields[:attributes] = @required[:attributes].dup
54
- @fields[:relationships] = @required[:relationships].dup
55
- if @optional
56
- @fields[:primary_id] = true if @optional[:primary_id]
57
- primary_types = @optional[:primary_types]
58
- @fields[:primary_types] = primary_types if primary_types
59
- @fields[:attributes].merge
60
- end
61
- end
62
-
63
- def validate!
64
- raise INVALID_DOCUMENT unless @document.data
65
- @data = @document.data
66
- if @data.respond_to?(:each)
67
- raise INVALID_DOCUMENT, 'The request MUST include a single resource' \
68
- ' object as primary data'
69
- end
70
- @attributes = @data.attributes
71
- @relationships = @data.relationships
72
- validate_primary!
73
- validate_fields!
74
- end
75
-
76
- def validate_primary!
77
- validate_id!
78
- validate_type!
79
- end
80
-
81
- def id_required?
82
- @required[:primary_id]
83
- end
84
-
85
- def id_permitted?
86
- @fields[:primary_id]
87
- end
88
-
89
- def validate_id!
90
- if @data.id.nil?
91
- raise INVALID_DOCUMENT,
92
- 'Expected id for primary resource' if id_required?
93
- else
94
- raise INVALID_DOCUMENT,
95
- 'Unexpected id for primary resource' unless id_permitted?
96
- end
97
- end
98
-
99
- def type_valid?
100
- return false if @required &&
101
- @required[:primary_types] &&
102
- !@required[:primary_types].include?(@data.type.to_sym)
103
- return false if @optional &&
104
- @optional[:primary_types] &&
105
- !@optional[:primary_types].include?(@data.type.to_sym)
106
- true
107
- end
108
-
109
- def validate_type!
110
- return if type_valid?
111
- raise INVALID_DOCUMENT,
112
- "Unexpected type #{@data.type} for primary resource"
113
- end
114
-
115
- def validate_fields!
116
- validate_attributes!
117
- validate_relationships!
118
- end
119
-
120
- def attr_permitted?(attr_key)
121
- return true unless @optional
122
- return true if @optional[:attributes].include?(attr_key.to_sym)
123
- @required && @required[:attributes].include?(attr_key.to_sym)
124
- end
125
-
126
- def validate_attributes!
127
- @attributes.keys.each do |attr_key|
128
- next if attr_permitted?(attr_key)
129
- raise INVALID_DOCUMENT, "Unexpected attribute #{attr_key}"
130
- end
131
- return unless @required
132
- @required[:attributes].each do |attr_key|
133
- next if @attributes.defined?(attr_key)
134
- raise INVALID_DOCUMENT, "Expected attribute #{attr_key}"
135
- end
136
- end
137
-
138
- def rel_permitted?(rel_key)
139
- return true unless @optional
140
- return true if @optional[:relationships].key?(rel_key.to_sym)
141
- @required && @required[:relationships].key?(rel_key.to_sym)
142
- end
143
-
144
- def validate_relationships!
145
- @relationships.keys.each do |rel_key|
146
- next if rel_permitted?(rel_key)
147
- raise INVALID_DOCUMENT, "Unexpected relationship #{rel_key}"
148
- end
149
- return unless @required
150
- @required[:relationships].keys.each do |rel_key|
151
- next if @relationships.defined?(rel_key)
152
- raise INVALID_DOCUMENT, "Expected relationship #{rel_key}"
153
- end
154
- validate_relationship_types!
155
- end
156
-
157
- def validate_relationship_types!
158
- rels = {}
159
- rels.merge!(@required.relationships) if @required
160
- rels.merge(@optional.relationships) if @optional
161
- rels.each do |key, hash|
162
- rel = @relationships[key.to_s]
163
- unless rel.data
164
- raise INVALID_DOCUMENT, "Expected data for relationship #{key}"
165
- end
166
-
167
- if hash[:arity] == :to_one
168
- validate_to_one_relationship_type!(rel, hash[:types])
169
- else
170
- validate_to_many_relationship_type!(rel, hash[:types])
171
- end
172
- end
173
- end
174
-
175
- def validate_to_one_relationship_type!(rel, types)
176
- if rel.collection?
177
- raise INVALID_DOCUMENT,
178
- "Expected relationship #{key} to be has_one"
179
- end
180
- return unless types && !types.include?(rel.data.type.to_sym)
181
- raise INVALID_DOCUMENT, "Unexpected type: #{rel.data.type} for " \
182
- "relationship #{key}"
183
- end
184
-
185
- def validate_to_many_relationship_type!(rel, types)
186
- unless rel.collection?
187
- raise INVALID_DOCUMENT,
188
- "Expected relationship #{key} to be has_many"
189
- end
190
- return unless types
191
- rel.data.each do |ri|
192
- unless types.include?(ri.type.to_sym)
193
- raise INVALID_DOCUMENT, "Unexpected type: #{ri.type} for " \
194
- "relationship #{key}"
195
- end
196
- end
197
- end
198
- end
199
- end
200
- end
@@ -1,7 +0,0 @@
1
- require 'jsonapi/parser/exceptions'
2
-
3
- module JSONAPI
4
- module Deserializable
5
- INVALID_DOCUMENT = JSONAPI::Parser::InvalidDocument
6
- end
7
- end
@@ -1,101 +0,0 @@
1
- module JSONAPI
2
- module Deserializable
3
- class Validations
4
- def initialize(validation_type, &block)
5
- @validation_type = validation_type
6
- @hash = {
7
- @validation_type => {
8
- attributes: [],
9
- relationships: []
10
- },
11
- types: {
12
- relationships: {}
13
- }
14
- }
15
- instance_eval(&block)
16
- end
17
-
18
- def to_h
19
- @hash
20
- end
21
-
22
- private
23
-
24
- # Define whether the +id+ of the primary resource should be part of
25
- # this list.
26
- def id
27
- validations_hash[:id] = true
28
- end
29
-
30
- # Define the allowed type for the primary resource.
31
- # @param [Symbol] value The value of the type.
32
- def type(value)
33
- types_hash[:primary] = Array(value)
34
- end
35
-
36
- # Define the allowed type for the primary resource.
37
- # @param [Array<Symbol>] values List of allowed values of the type.
38
- def types(values)
39
- types_hash[:primary] = values
40
- end
41
-
42
- # Define an attribute with given key.
43
- # @param [Symbol] key The key of the attribute in the payload.
44
- def attribute(key)
45
- validations_hash[:attributes] << key
46
- end
47
-
48
- # TODO(beauby): Decide whether type: 'users' / types: [...] is better.
49
- #
50
- # @overload has_one(key)
51
- # Define a has_one relationship with given key.
52
- # @param [Symbol] key The key of the relationship in the payload.
53
- #
54
- # @overload has_one(key, type)
55
- # Define a has_one relationship with given key.
56
- # @param [Symbol] key The key of the relationship in the payload.
57
- # @param [Symbol] type The expected type of the relationship value.
58
- #
59
- # @overload has_one(key, types)
60
- # Define a has_one relationship with given key.
61
- # @param [Symbol] key The key of the relationship in the payload.
62
- # @param [Array<Symbol>] type List of acceptable types for the
63
- # relationship value.
64
- def has_many(key, types = nil)
65
- validations_hash[:relationships] << key
66
- types_hash[:relationships][key] = { kind: :has_many }
67
- return unless types
68
- types_hash[:relationships][key][:types] = Array(types)
69
- end
70
-
71
- # @overload has_one(key)
72
- # Define a has_one relationship with given key.
73
- # @param [Symbol] key The key of the relationship in the payload.
74
- #
75
- # @overload has_one(key, type)
76
- # Define a has_one relationship with given key.
77
- # @param [Symbol] key The key of the relationship in the payload.
78
- # @param [Symbol] type The expected type of the relationship value.
79
- #
80
- # @overload has_one(key, types)
81
- # Define a has_one relationship with given key.
82
- # @param [Symbol] key The key of the relationship in the payload.
83
- # @param [Array<Symbol>] type List of acceptable types for the
84
- # relationship value.
85
- def has_one(key, types = nil)
86
- validations_hash[:relationships] << key
87
- types_hash[:relationships][key] = { kind: :has_one }
88
- return unless types
89
- types_hash[:relationships][key][:types] = Array(types)
90
- end
91
-
92
- def validations_hash
93
- @hash[@validation_type]
94
- end
95
-
96
- def types_hash
97
- @hash[:types]
98
- end
99
- end
100
- end
101
- end