jsonapi 0.1.1.beta2 → 0.1.1.beta6
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 +9 -111
- data/lib/jsonapi.rb +2 -18
- metadata +26 -45
- data/.gitignore +0 -36
- data/.travis.yml +0 -6
- data/Gemfile +0 -3
- data/Gemfile.lock +0 -36
- data/LICENSE +0 -21
- data/Rakefile +0 -7
- data/jsonapi_parser.gemspec +0 -24
- data/lib/jsonapi/attributes.rb +0 -41
- data/lib/jsonapi/document.rb +0 -126
- data/lib/jsonapi/error.rb +0 -27
- data/lib/jsonapi/exceptions.rb +0 -4
- data/lib/jsonapi/include_directive.rb +0 -67
- data/lib/jsonapi/include_directive/parser.rb +0 -66
- data/lib/jsonapi/jsonapi.rb +0 -19
- data/lib/jsonapi/link.rb +0 -41
- data/lib/jsonapi/links.rb +0 -34
- data/lib/jsonapi/parse.rb +0 -18
- data/lib/jsonapi/relationship.rb +0 -57
- data/lib/jsonapi/relationships.rb +0 -41
- data/lib/jsonapi/resource.rb +0 -46
- data/lib/jsonapi/resource_identifier.rb +0 -36
- data/lib/jsonapi/version.rb +0 -3
- data/spec/duplicates_spec.rb +0 -95
- data/spec/full_linkage_spec.rb +0 -161
- data/spec/include_directive/parser_spec.rb +0 -59
- data/spec/include_directive_spec.rb +0 -47
- data/spec/parser_spec.rb +0 -97
@@ -1,41 +0,0 @@
|
|
1
|
-
module JSONAPI
|
2
|
-
# c.f. http://jsonapi.org/format/#document-resource-object-relationships
|
3
|
-
class Relationships
|
4
|
-
include Enumerable
|
5
|
-
|
6
|
-
def initialize(relationships_hash, options = {})
|
7
|
-
fail InvalidDocument,
|
8
|
-
"the value of 'relationships' MUST be an object" unless
|
9
|
-
relationships_hash.is_a?(Hash)
|
10
|
-
|
11
|
-
@hash = relationships_hash
|
12
|
-
@relationships = {}
|
13
|
-
relationships_hash.each do |rel_name, rel_hash|
|
14
|
-
@relationships[rel_name.to_s] = Relationship.new(rel_hash, options)
|
15
|
-
define_singleton_method(rel_name) do
|
16
|
-
@relationships[rel_name.to_s]
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def to_hash
|
22
|
-
@hash
|
23
|
-
end
|
24
|
-
|
25
|
-
def each(&block)
|
26
|
-
@relationships.each(&block)
|
27
|
-
end
|
28
|
-
|
29
|
-
def [](rel_name)
|
30
|
-
@relationships[rel_name.to_s]
|
31
|
-
end
|
32
|
-
|
33
|
-
def defined?(rel_name)
|
34
|
-
@relationships.key?(rel_name.to_s)
|
35
|
-
end
|
36
|
-
|
37
|
-
def keys
|
38
|
-
@relationships.keys
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
data/lib/jsonapi/resource.rb
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
module JSONAPI
|
2
|
-
# c.f. http://jsonapi.org/format/#document-resource-objects
|
3
|
-
class Resource
|
4
|
-
attr_reader :id, :type, :attributes, :relationships, :links, :meta
|
5
|
-
|
6
|
-
def initialize(resource_hash, options = {})
|
7
|
-
@hash = resource_hash
|
8
|
-
@options = options.dup
|
9
|
-
@id_optional = @options.delete(:id_optional)
|
10
|
-
validate!(resource_hash)
|
11
|
-
@id = resource_hash['id']
|
12
|
-
@type = resource_hash['type']
|
13
|
-
@attributes_hash = resource_hash['attributes'] || {}
|
14
|
-
@attributes = Attributes.new(@attributes_hash, @options)
|
15
|
-
@relationships_hash = resource_hash['relationships'] || {}
|
16
|
-
@relationships = Relationships.new(@relationships_hash, @options)
|
17
|
-
@links_hash = resource_hash['links'] || {}
|
18
|
-
@links = Links.new(@links_hash, @options)
|
19
|
-
@meta = resource_hash['meta'] if resource_hash.key?('meta')
|
20
|
-
end
|
21
|
-
|
22
|
-
def to_hash
|
23
|
-
@hash
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
def validate!(resource_hash)
|
29
|
-
case
|
30
|
-
when !@id_optional && !resource_hash.key?('id')
|
31
|
-
# We might want to take care of
|
32
|
-
# > Exception: The id member is not required when the resource object
|
33
|
-
# > originates at the client and represents a new resource to be created
|
34
|
-
# > on the server.
|
35
|
-
# in the future.
|
36
|
-
fail InvalidDocument, "a resource object MUST contain an 'id'"
|
37
|
-
when !@id_optional && !resource_hash['id'].is_a?(String)
|
38
|
-
fail InvalidDocument, "the value of 'id' MUST be a string"
|
39
|
-
when !resource_hash.key?('type')
|
40
|
-
fail InvalidDocument, "a resource object MUST contain a 'type'"
|
41
|
-
when !resource_hash['type'].is_a?(String)
|
42
|
-
fail InvalidDocument, "the value of 'type' MUST be a string"
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
@@ -1,36 +0,0 @@
|
|
1
|
-
module JSONAPI
|
2
|
-
# c.f. http://jsonapi.org/format/#document-resource-identifier-objects
|
3
|
-
class ResourceIdentifier
|
4
|
-
attr_reader :id, :type
|
5
|
-
|
6
|
-
def initialize(resource_identifier_hash, options = {})
|
7
|
-
@hash = resource_identifier_hash
|
8
|
-
|
9
|
-
validate!(resource_identifier_hash)
|
10
|
-
|
11
|
-
@id = resource_identifier_hash['id']
|
12
|
-
@type = resource_identifier_hash['type']
|
13
|
-
end
|
14
|
-
|
15
|
-
def to_hash
|
16
|
-
@hash
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def validate!(resource_identifier_hash)
|
22
|
-
case
|
23
|
-
when !resource_identifier_hash.key?('id')
|
24
|
-
fail InvalidDocument,
|
25
|
-
"a resource identifier object MUST contain an 'id'"
|
26
|
-
when !resource_identifier_hash['id'].is_a?(String)
|
27
|
-
fail InvalidDocument, "the value of 'id' MUST be a string"
|
28
|
-
when !resource_identifier_hash.key?('type')
|
29
|
-
fail InvalidDocument,
|
30
|
-
"a resource identifier object MUST contain a 'type'"
|
31
|
-
when !resource_identifier_hash['type'].is_a?(String)
|
32
|
-
fail InvalidDocument, "the value of 'type' MUST be a string"
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
data/lib/jsonapi/version.rb
DELETED
data/spec/duplicates_spec.rb
DELETED
@@ -1,95 +0,0 @@
|
|
1
|
-
require 'jsonapi'
|
2
|
-
|
3
|
-
describe JSONAPI, '#parse' do
|
4
|
-
it 'succeeds when there are no duplicates' do
|
5
|
-
payload = {
|
6
|
-
'data' => [
|
7
|
-
{
|
8
|
-
'type' => 'articles',
|
9
|
-
'id' => '1',
|
10
|
-
'attributes' => {
|
11
|
-
'title' => 'JSON API paints my bikeshed!'
|
12
|
-
},
|
13
|
-
'links' => {
|
14
|
-
'self' => 'http://example.com/articles/1'
|
15
|
-
},
|
16
|
-
'relationships' => {
|
17
|
-
'author' => {
|
18
|
-
'links' => {
|
19
|
-
'self' => 'http://example.com/articles/1/relationships/author',
|
20
|
-
'related' => 'http://example.com/articles/1/author'
|
21
|
-
},
|
22
|
-
'data' => { 'type' => 'people', 'id' => '9' }
|
23
|
-
},
|
24
|
-
'journal' => {
|
25
|
-
'data' => nil
|
26
|
-
},
|
27
|
-
'comments' => {
|
28
|
-
'links' => {
|
29
|
-
'self' => 'http://example.com/articles/1/relationships/comments',
|
30
|
-
'related' => 'http://example.com/articles/1/comments'
|
31
|
-
},
|
32
|
-
'data' => [
|
33
|
-
{ 'type' => 'comments', 'id' => '5' },
|
34
|
-
{ 'type' => 'comments', 'id' => '12' }
|
35
|
-
]
|
36
|
-
}
|
37
|
-
}
|
38
|
-
}]
|
39
|
-
}
|
40
|
-
|
41
|
-
JSONAPI.parse(payload, verify_duplicates: true)
|
42
|
-
end
|
43
|
-
|
44
|
-
it 'fails when there are duplicates within primary data' do
|
45
|
-
payload = {
|
46
|
-
'data' => [
|
47
|
-
{
|
48
|
-
'type' => 'articles',
|
49
|
-
'id' => '1'
|
50
|
-
}, {
|
51
|
-
'type' => 'articles',
|
52
|
-
'id' => '1'
|
53
|
-
}]
|
54
|
-
}
|
55
|
-
|
56
|
-
expect { JSONAPI.parse(payload, verify_duplicates: true) }
|
57
|
-
.to raise_error(JSONAPI::InvalidDocument)
|
58
|
-
end
|
59
|
-
|
60
|
-
it 'fails when there are duplicates within included' do
|
61
|
-
payload = {
|
62
|
-
'data' => nil,
|
63
|
-
'included' => [
|
64
|
-
{
|
65
|
-
'type' => 'articles',
|
66
|
-
'id' => '1'
|
67
|
-
}, {
|
68
|
-
'type' => 'articles',
|
69
|
-
'id' => '1'
|
70
|
-
}]
|
71
|
-
}
|
72
|
-
|
73
|
-
expect { JSONAPI.parse(payload, verify_duplicates: true) }
|
74
|
-
.to raise_error(JSONAPI::InvalidDocument)
|
75
|
-
end
|
76
|
-
|
77
|
-
it 'fails when there are duplicates within primary data' do
|
78
|
-
payload = {
|
79
|
-
'data' => [
|
80
|
-
{
|
81
|
-
'type' => 'articles',
|
82
|
-
'id' => '1'
|
83
|
-
}
|
84
|
-
],
|
85
|
-
'included' => [
|
86
|
-
{
|
87
|
-
'type' => 'articles',
|
88
|
-
'id' => '1'
|
89
|
-
}]
|
90
|
-
}
|
91
|
-
|
92
|
-
expect { JSONAPI.parse(payload, verify_duplicates: true) }
|
93
|
-
.to raise_error(JSONAPI::InvalidDocument)
|
94
|
-
end
|
95
|
-
end
|
data/spec/full_linkage_spec.rb
DELETED
@@ -1,161 +0,0 @@
|
|
1
|
-
require 'jsonapi'
|
2
|
-
|
3
|
-
describe JSONAPI, '#parse' do
|
4
|
-
it 'succeeds when no included property is provided' do
|
5
|
-
payload = {
|
6
|
-
'data' => [
|
7
|
-
{
|
8
|
-
'type' => 'articles',
|
9
|
-
'id' => '1',
|
10
|
-
'attributes' => {
|
11
|
-
'title' => 'JSON API paints my bikeshed!'
|
12
|
-
},
|
13
|
-
'links' => {
|
14
|
-
'self' => 'http://example.com/articles/1'
|
15
|
-
},
|
16
|
-
'relationships' => {
|
17
|
-
'author' => {
|
18
|
-
'links' => {
|
19
|
-
'self' => 'http://example.com/articles/1/relationships/author',
|
20
|
-
'related' => 'http://example.com/articles/1/author'
|
21
|
-
},
|
22
|
-
'data' => { 'type' => 'people', 'id' => '9' }
|
23
|
-
},
|
24
|
-
'journal' => {
|
25
|
-
'data' => nil
|
26
|
-
},
|
27
|
-
'comments' => {
|
28
|
-
'links' => {
|
29
|
-
'self' => 'http://example.com/articles/1/relationships/comments',
|
30
|
-
'related' => 'http://example.com/articles/1/comments'
|
31
|
-
},
|
32
|
-
'data' => [
|
33
|
-
{ 'type' => 'comments', 'id' => '5' },
|
34
|
-
{ 'type' => 'comments', 'id' => '12' }
|
35
|
-
]
|
36
|
-
}
|
37
|
-
}
|
38
|
-
}]
|
39
|
-
}
|
40
|
-
|
41
|
-
JSONAPI.parse(payload, verify_linkage: true)
|
42
|
-
end
|
43
|
-
|
44
|
-
it 'succeeds when full linkage is respected' do
|
45
|
-
payload = {
|
46
|
-
'data' => [
|
47
|
-
{
|
48
|
-
'type' => 'articles',
|
49
|
-
'id' => '1',
|
50
|
-
'attributes' => {
|
51
|
-
'title' => 'JSON API paints my bikeshed!'
|
52
|
-
},
|
53
|
-
'links' => {
|
54
|
-
'self' => 'http://example.com/articles/1'
|
55
|
-
},
|
56
|
-
'relationships' => {
|
57
|
-
'author' => {
|
58
|
-
'links' => {
|
59
|
-
'self' => 'http://example.com/articles/1/relationships/author',
|
60
|
-
'related' => 'http://example.com/articles/1/author'
|
61
|
-
},
|
62
|
-
'data' => { 'type' => 'people', 'id' => '9' }
|
63
|
-
},
|
64
|
-
'journal' => {
|
65
|
-
'data' => nil
|
66
|
-
},
|
67
|
-
'comments' => {
|
68
|
-
'links' => {
|
69
|
-
'self' => 'http://example.com/articles/1/relationships/comments',
|
70
|
-
'related' => 'http://example.com/articles/1/comments'
|
71
|
-
},
|
72
|
-
'data' => [
|
73
|
-
{ 'type' => 'comments', 'id' => '5' },
|
74
|
-
{ 'type' => 'comments', 'id' => '12' }
|
75
|
-
]
|
76
|
-
}
|
77
|
-
}
|
78
|
-
}],
|
79
|
-
'included' => [
|
80
|
-
{
|
81
|
-
'type' => 'comments',
|
82
|
-
'id' => '5'
|
83
|
-
}, {
|
84
|
-
'type' => 'comments',
|
85
|
-
'id' => '12'
|
86
|
-
}, {
|
87
|
-
'type' => 'comments',
|
88
|
-
'id' => '13'
|
89
|
-
}, {
|
90
|
-
'type' => 'people',
|
91
|
-
'id' => '9',
|
92
|
-
'relationships' => {
|
93
|
-
'comments' => {
|
94
|
-
'data' => [
|
95
|
-
{
|
96
|
-
'type' => 'comments',
|
97
|
-
'id' => '13'
|
98
|
-
}
|
99
|
-
]
|
100
|
-
}
|
101
|
-
}
|
102
|
-
}
|
103
|
-
]
|
104
|
-
}
|
105
|
-
|
106
|
-
JSONAPI.parse(payload, verify_linkage: true)
|
107
|
-
end
|
108
|
-
|
109
|
-
it 'fails when full linkage is not respected' do
|
110
|
-
payload = {
|
111
|
-
'data' => [
|
112
|
-
{
|
113
|
-
'type' => 'articles',
|
114
|
-
'id' => '1',
|
115
|
-
'attributes' => {
|
116
|
-
'title' => 'JSON API paints my bikeshed!'
|
117
|
-
},
|
118
|
-
'links' => {
|
119
|
-
'self' => 'http://example.com/articles/1'
|
120
|
-
},
|
121
|
-
'relationships' => {
|
122
|
-
'author' => {
|
123
|
-
'links' => {
|
124
|
-
'self' => 'http://example.com/articles/1/relationships/author',
|
125
|
-
'related' => 'http://example.com/articles/1/author'
|
126
|
-
},
|
127
|
-
'data' => { 'type' => 'people', 'id' => '9' }
|
128
|
-
},
|
129
|
-
'journal' => {
|
130
|
-
'data' => nil
|
131
|
-
},
|
132
|
-
'comments' => {
|
133
|
-
'links' => {
|
134
|
-
'self' => 'http://example.com/articles/1/relationships/comments',
|
135
|
-
'related' => 'http://example.com/articles/1/comments'
|
136
|
-
},
|
137
|
-
'data' => [
|
138
|
-
{ 'type' => 'comments', 'id' => '5' },
|
139
|
-
{ 'type' => 'comments', 'id' => '12' }
|
140
|
-
]
|
141
|
-
}
|
142
|
-
}
|
143
|
-
}],
|
144
|
-
'included' => [
|
145
|
-
{
|
146
|
-
'type' => 'comments',
|
147
|
-
'id' => '5'
|
148
|
-
}, {
|
149
|
-
'type' => 'comments',
|
150
|
-
'id' => '12'
|
151
|
-
}, {
|
152
|
-
'type' => 'comments',
|
153
|
-
'id' => '13'
|
154
|
-
}
|
155
|
-
]
|
156
|
-
}
|
157
|
-
|
158
|
-
expect { JSONAPI.parse(payload, verify_linkage: true) }
|
159
|
-
.to raise_error(JSONAPI::InvalidDocument)
|
160
|
-
end
|
161
|
-
end
|
@@ -1,59 +0,0 @@
|
|
1
|
-
require 'jsonapi/include_directive'
|
2
|
-
|
3
|
-
describe JSONAPI::IncludeDirective::Parser, '.parse_include_args' do
|
4
|
-
it 'handles arrays of symbols and hashes' do
|
5
|
-
args = [:friends,
|
6
|
-
comments: [:author],
|
7
|
-
posts: [:author,
|
8
|
-
comments: [:author]]]
|
9
|
-
hash = JSONAPI::IncludeDirective::Parser.parse_include_args(args)
|
10
|
-
expected = {
|
11
|
-
friends: {},
|
12
|
-
comments: { author: {} },
|
13
|
-
posts: { author: {}, comments: { author: {} } }
|
14
|
-
}
|
15
|
-
|
16
|
-
expect(hash).to eq expected
|
17
|
-
end
|
18
|
-
|
19
|
-
it 'handles strings with spaces' do
|
20
|
-
str = 'friends, comments.author, posts.author, posts.comments.author'
|
21
|
-
hash = JSONAPI::IncludeDirective::Parser.parse_include_args(str)
|
22
|
-
expected = {
|
23
|
-
friends: {},
|
24
|
-
comments: { author: {} },
|
25
|
-
posts: { author: {}, comments: { author: {} } }
|
26
|
-
}
|
27
|
-
|
28
|
-
expect(hash).to eq expected
|
29
|
-
end
|
30
|
-
|
31
|
-
it 'handles common prefixes in strings' do
|
32
|
-
args = ['friends', 'comments.author', 'posts.author',
|
33
|
-
'posts.comments.author']
|
34
|
-
hash = JSONAPI::IncludeDirective::Parser.parse_include_args(args)
|
35
|
-
expected = {
|
36
|
-
friends: {},
|
37
|
-
comments: { author: {} },
|
38
|
-
posts: { author: {}, comments: { author: {} } }
|
39
|
-
}
|
40
|
-
|
41
|
-
expect(hash).to eq expected
|
42
|
-
end
|
43
|
-
|
44
|
-
it 'handles an empty string' do
|
45
|
-
args = ''
|
46
|
-
hash = JSONAPI::IncludeDirective::Parser.parse_include_args(args)
|
47
|
-
expected = {}
|
48
|
-
|
49
|
-
expect(hash).to eq expected
|
50
|
-
end
|
51
|
-
|
52
|
-
it 'handles an empty array' do
|
53
|
-
args = []
|
54
|
-
hash = JSONAPI::IncludeDirective::Parser.parse_include_args(args)
|
55
|
-
expected = {}
|
56
|
-
|
57
|
-
expect(hash).to eq expected
|
58
|
-
end
|
59
|
-
end
|