json_api_ruby 0.3.0 → 0.4.0
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/CHANGELOG.md +3 -0
- data/lib/json_api_ruby.rb +1 -0
- data/lib/json_api_ruby/configuration.rb +10 -2
- data/lib/json_api_ruby/includes.rb +36 -0
- data/lib/json_api_ruby/resource.rb +6 -1
- data/lib/json_api_ruby/resources/base.rb +2 -10
- data/lib/json_api_ruby/resources/dsl.rb +5 -0
- data/lib/json_api_ruby/resources/relationships.rb +7 -6
- data/lib/json_api_ruby/serializer.rb +36 -48
- data/lib/json_api_ruby/version.rb +1 -1
- data/spec/json_api_ruby/configuration_spec.rb +22 -0
- data/spec/json_api_ruby/includes_spec.rb +36 -0
- data/spec/json_api_ruby/resource_spec.rb +1 -1
- data/spec/json_api_ruby/resources/base_spec.rb +25 -0
- data/spec/json_api_ruby/resources/relationships_spec.rb +17 -5
- data/spec/json_api_ruby/serializer_spec.rb +9 -0
- data/spec/support/resource_objects.rb +2 -1
- metadata +26 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 018c57ac3ac726a576720f582783604eb22151a7
|
4
|
+
data.tar.gz: c8d50c7117d9b54654ad484b7e011e82a8402c8b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c40fd216bd9f2809c83bf7ecf47372b23772747fb5827c373d52d357a4a22b05b8f03a97eb62a85e1816f6c87009ea32c8e28a5ede090dda103375f428bae8d8
|
7
|
+
data.tar.gz: 8ea27ee8bb37753a4a8aa098d1529a69a0feff3d49d7b859dc3d2300bc14f68c5ddeb051eb90ea12162c0532907806b5505196d16e2e8076bdf0af84895746ab
|
data/CHANGELOG.md
CHANGED
data/lib/json_api_ruby.rb
CHANGED
@@ -1,9 +1,17 @@
|
|
1
1
|
module JsonApi
|
2
2
|
class Configuration
|
3
|
-
|
3
|
+
attr_accessor :base_url
|
4
|
+
attr_accessor :use_links
|
5
|
+
|
6
|
+
DEFAULTS = {
|
7
|
+
base_url: 'http://localhost:3000',
|
8
|
+
use_links: true
|
9
|
+
}
|
4
10
|
|
5
11
|
def initialize
|
6
|
-
|
12
|
+
DEFAULTS.each do |key, value|
|
13
|
+
self.instance_variable_set("@#{key}", value)
|
14
|
+
end
|
7
15
|
end
|
8
16
|
end
|
9
17
|
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module JsonApi
|
2
|
+
# Builds a traversible representation of the included resources
|
3
|
+
class Includes
|
4
|
+
attr_reader :name
|
5
|
+
attr_writer :includes
|
6
|
+
attr_accessor :next
|
7
|
+
|
8
|
+
# Returns:
|
9
|
+
# #<Includes>
|
10
|
+
def self.parse_includes(includes)
|
11
|
+
first_include = self.new
|
12
|
+
|
13
|
+
split_includes = Array(includes).map{|inc| inc.to_s.split('.')}
|
14
|
+
if split_includes.blank?
|
15
|
+
return first_include
|
16
|
+
end
|
17
|
+
|
18
|
+
first_array = Array(split_includes.first)
|
19
|
+
other_arrays = split_includes[1..-1]
|
20
|
+
zipped = first_array.zip(*other_arrays)
|
21
|
+
first_array = zipped.shift
|
22
|
+
first_include.includes = first_array.uniq.compact
|
23
|
+
zipped.inject(first_include) do |base_include, object_name|
|
24
|
+
new_include = self.new
|
25
|
+
new_include.includes = object_name.uniq.compact
|
26
|
+
base_include.next = new_include
|
27
|
+
new_include
|
28
|
+
end
|
29
|
+
first_include
|
30
|
+
end
|
31
|
+
|
32
|
+
def includes
|
33
|
+
@includes || []
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -9,6 +9,7 @@ module JsonApi
|
|
9
9
|
|
10
10
|
def self.inherited(subclass)
|
11
11
|
subclass.id_field(@_id_field || :id)
|
12
|
+
subclass.use_links(@_use_links || JsonApi.configuration.use_links)
|
12
13
|
end
|
13
14
|
|
14
15
|
# Can be set using `id_field` in the created resource class like so:
|
@@ -27,6 +28,10 @@ module JsonApi
|
|
27
28
|
_model.class.to_s.underscore.pluralize
|
28
29
|
end
|
29
30
|
|
31
|
+
def use_links
|
32
|
+
self.class._use_links
|
33
|
+
end
|
34
|
+
|
30
35
|
# Makes the underlying object available to subclasses so we can do things
|
31
36
|
# like
|
32
37
|
#
|
@@ -53,7 +58,7 @@ module JsonApi
|
|
53
58
|
def initialize(model, options={})
|
54
59
|
options.stringify_keys!
|
55
60
|
@_model = model
|
56
|
-
@includes =
|
61
|
+
@includes = options.fetch('include', [])
|
57
62
|
build_object_graph # base module method
|
58
63
|
end
|
59
64
|
end
|
@@ -13,17 +13,10 @@ module JsonApi
|
|
13
13
|
resource_hash['relationships'][relationship.name] = relationship.to_hash
|
14
14
|
end
|
15
15
|
|
16
|
-
resource_hash['links'] = links_hash
|
16
|
+
resource_hash['links'] = links_hash if self.use_links
|
17
17
|
resource_hash
|
18
18
|
end
|
19
19
|
|
20
|
-
# Very basic. Eventually this will need to parse things like
|
21
|
-
# "article.comments" and "article-comments", so, leaving the method here
|
22
|
-
# but only supporting the most basic of things
|
23
|
-
def parse_for_includes(includes)
|
24
|
-
Array(includes).map(&:to_s)
|
25
|
-
end
|
26
|
-
|
27
20
|
def identifier_hash
|
28
21
|
{ 'id' => self.id, 'type' => self.type }
|
29
22
|
end
|
@@ -48,8 +41,7 @@ module JsonApi
|
|
48
41
|
def build_object_graph
|
49
42
|
@relationships ||= []
|
50
43
|
relationships_array.each do |relationship|
|
51
|
-
|
52
|
-
rel = relationship.build_resources({parent_resource: self, included: included})
|
44
|
+
rel = relationship.build_resources({parent_resource: self, included: includes})
|
53
45
|
@relationships << rel
|
54
46
|
end
|
55
47
|
end
|
@@ -2,6 +2,7 @@ module JsonApi
|
|
2
2
|
module Resources
|
3
3
|
module DSL
|
4
4
|
attr :_id_field
|
5
|
+
attr :_use_links
|
5
6
|
attr :fields
|
6
7
|
attr :relationships
|
7
8
|
|
@@ -29,6 +30,10 @@ module JsonApi
|
|
29
30
|
@_id_field = key
|
30
31
|
end
|
31
32
|
|
33
|
+
def use_links(yesno)
|
34
|
+
@_use_links = yesno
|
35
|
+
end
|
36
|
+
|
32
37
|
private
|
33
38
|
def add_relationship(object_name, cardinality, options)
|
34
39
|
@relationships ||= []
|
@@ -60,21 +60,22 @@ module JsonApi
|
|
60
60
|
@resources = []
|
61
61
|
@parent = options.fetch(:parent_resource)
|
62
62
|
@parent_model = parent._model
|
63
|
-
@included = options.fetch(:included,
|
63
|
+
@included = options.fetch(:included, {})
|
64
64
|
@explicit_resource_class = options.fetch(:explicit_resource_class)
|
65
65
|
end
|
66
66
|
|
67
67
|
def included?
|
68
|
-
included
|
68
|
+
included.present? && included.includes.include?(@name)
|
69
69
|
end
|
70
70
|
|
71
71
|
def to_hash
|
72
|
-
return_hash =
|
72
|
+
return_hash = {}
|
73
|
+
return_hash.merge!(relationship_links) if JsonApi.configuration.use_links
|
73
74
|
return_hash.merge!(data) if included?
|
74
75
|
return_hash
|
75
76
|
end
|
76
77
|
|
77
|
-
def
|
78
|
+
def relationship_links
|
78
79
|
{
|
79
80
|
'links' => {
|
80
81
|
'self' => JsonApi.configuration.base_url + parent.self_link_path + "/relationships/#{name}",
|
@@ -97,7 +98,7 @@ module JsonApi
|
|
97
98
|
return if resource_model.blank?
|
98
99
|
|
99
100
|
resource_class = Discovery.resource_for_name(resource_model, options.merge(parent_resource: parent, resource_class: explicit_resource_class))
|
100
|
-
@resources << resource_class.new(resource_model)
|
101
|
+
@resources << resource_class.new(resource_model, options.merge({include: included.next}))
|
101
102
|
end
|
102
103
|
|
103
104
|
def resource_object
|
@@ -123,7 +124,7 @@ module JsonApi
|
|
123
124
|
|
124
125
|
parent_model.send(name).each do |resource_model|
|
125
126
|
resource_class = Discovery.resource_for_name(resource_model, options.merge(parent_resource: parent, resource_class: explicit_resource_class))
|
126
|
-
@resources << resource_class.new(resource_model)
|
127
|
+
@resources << resource_class.new(resource_model, options.merge({include: included.next}))
|
127
128
|
end
|
128
129
|
end
|
129
130
|
|
@@ -14,86 +14,74 @@ module JsonApi
|
|
14
14
|
if !object.nil? && object.respond_to?(:to_a)
|
15
15
|
serializer = CollectionSerializer.new(object, options)
|
16
16
|
else
|
17
|
-
serializer =
|
17
|
+
serializer = ObjectSerializer.new(object, options)
|
18
18
|
end
|
19
19
|
serializer.to_hash
|
20
20
|
end
|
21
21
|
|
22
22
|
class Serializer
|
23
|
+
attr_reader :object
|
24
|
+
|
23
25
|
def initialize(object, options)
|
24
26
|
@meta = options.fetch('meta', Hash.new).stringify_keys
|
25
27
|
@object = object
|
26
28
|
@includes = options.fetch('include', [])
|
27
|
-
|
28
|
-
|
29
|
+
@resource_class = options.fetch('resource_class', nil)
|
30
|
+
end
|
31
|
+
|
32
|
+
def resource(object)
|
33
|
+
resource_name = "#{object.class.to_s.underscore}_resource".classify
|
34
|
+
klass_name = @resource_class || resource_name
|
35
|
+
resource_klass = Resources::Discovery.resource_for_name(object, resource_class: klass_name)
|
36
|
+
resource_klass.new(object, include: Includes.parse_includes(@includes))
|
37
|
+
end
|
38
|
+
|
39
|
+
def assemble_included_data(included_resources)
|
40
|
+
included_resources.map(&:to_hash)
|
29
41
|
end
|
30
42
|
|
43
|
+
def find_included_resources(object_resource)
|
44
|
+
included_resources = object_resource.relationships.select {|rel| rel.included?}.flat_map {|rel| rel.resources }
|
45
|
+
included_resources += included_resources.flat_map {|res| find_included_resources(res) }
|
46
|
+
included_resources.flatten
|
47
|
+
included_resources.uniq { |rel| rel.id + rel.type }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class ObjectSerializer < Serializer
|
31
52
|
def to_hash
|
53
|
+
included_resources = []
|
32
54
|
if @object.nil?
|
33
55
|
serialized = { 'data' => nil }
|
34
56
|
else
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
relationships = resource.relationships
|
39
|
-
included_data = assemble_included_data(relationships)
|
40
|
-
|
41
|
-
if included_data.present?
|
42
|
-
included_data.uniq! do |inc_data|
|
43
|
-
inc_data['id'] + inc_data['type']
|
44
|
-
end
|
45
|
-
serialized['included'] = included_data
|
46
|
-
end
|
57
|
+
object_resource = resource(@object)
|
58
|
+
serialized = { 'data' => object_resource.to_hash }
|
59
|
+
included_resources += find_included_resources(object_resource)
|
47
60
|
end
|
48
61
|
|
62
|
+
serialized['included'] = assemble_included_data(included_resources) if included_resources.present?
|
49
63
|
serialized['meta'] = @meta if @meta.present?
|
50
|
-
serialized
|
51
|
-
end
|
52
64
|
|
53
|
-
|
54
|
-
relationships.flat_map do |relationship|
|
55
|
-
next if relationship.resources.blank?
|
56
|
-
relationship.resources.map(&:to_hash)
|
57
|
-
end.compact
|
65
|
+
serialized
|
58
66
|
end
|
59
67
|
end
|
60
68
|
|
61
|
-
class CollectionSerializer
|
62
|
-
def initialize(objects, options = {})
|
63
|
-
@meta = options.fetch('meta', Hash.new).stringify_keys
|
64
|
-
@objects = objects
|
65
|
-
@includes = options.fetch('include', [])
|
66
|
-
@resource_class = options.fetch('resource_class', nil)
|
67
|
-
end
|
68
|
-
|
69
|
+
class CollectionSerializer < Serializer
|
69
70
|
def to_hash
|
70
71
|
serialized = {}
|
71
72
|
included_resources = []
|
72
73
|
|
73
|
-
data_array = @
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
resource = resource_klass.new(object, include: @includes)
|
78
|
-
included_resources += resource.relationships.select {|rel| rel.included?}.flat_map {|rel| rel.resources }
|
79
|
-
|
80
|
-
resource.to_hash
|
81
|
-
end
|
82
|
-
|
83
|
-
included_resources.uniq! do |rel|
|
84
|
-
rel.id + rel.type
|
74
|
+
data_array = Array(@object).map do |object|
|
75
|
+
object_resource = resource(object)
|
76
|
+
included_resources += find_included_resources(object_resource)
|
77
|
+
object_resource.to_hash
|
85
78
|
end
|
86
79
|
|
87
80
|
serialized['data'] = data_array
|
88
|
-
|
89
|
-
serialized['meta'] = @meta if @meta.present?
|
90
81
|
serialized['included'] = assemble_included_data(included_resources) if included_resources.present?
|
82
|
+
serialized['meta'] = @meta if @meta.present?
|
91
83
|
|
92
84
|
serialized
|
93
85
|
end
|
94
|
-
|
95
|
-
def assemble_included_data(included_resources)
|
96
|
-
included_resources.map(&:to_hash)
|
97
|
-
end
|
98
86
|
end
|
99
87
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe JsonApi::Configuration do
|
4
|
+
subject('configuration') { JsonApi.configuration }
|
5
|
+
specify { expect(subject.base_url).to eq 'http://localhost:3000' }
|
6
|
+
specify { expect(subject.use_links).to be_truthy }
|
7
|
+
|
8
|
+
it 'allows overidding the base url' do
|
9
|
+
subject.base_url = 'https://google.com'
|
10
|
+
expect(subject.base_url).to eq 'https://google.com'
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'allows overidding the use_links option' do
|
14
|
+
subject.use_links = false
|
15
|
+
expect(subject.use_links).to be_falsy
|
16
|
+
end
|
17
|
+
|
18
|
+
after(:all) do
|
19
|
+
JsonApi.configuration.base_url = 'http://localhost:3000'
|
20
|
+
JsonApi.configuration.use_links = true
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe JsonApi::Includes do
|
4
|
+
context 'with nil' do
|
5
|
+
subject(:parsed_with_nil) { described_class.parse_includes(nil) }
|
6
|
+
specify { expect(parsed_with_nil.includes).to eq [] }
|
7
|
+
specify { expect(parsed_with_nil.next).to be_nil }
|
8
|
+
end
|
9
|
+
|
10
|
+
context 'with nested resources using the "." syntax' do
|
11
|
+
it 'has an includes array' do
|
12
|
+
parsed_includes = described_class.parse_includes(['thingone', 'thingtwo'])
|
13
|
+
expect(parsed_includes.includes).to eq ['thingone', 'thingtwo']
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'has a reference to nested objects' do
|
17
|
+
parsed_includes = described_class.parse_includes(['thingone.thingtwo'])
|
18
|
+
expect(parsed_includes.next.includes).to eq ['thingtwo']
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'handles triple nesting' do
|
22
|
+
parsed_includes = described_class.parse_includes(['thingone.thingtwo.thingthree'])
|
23
|
+
expect(parsed_includes.next.next.includes).to eq ['thingthree']
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'complex includes' do
|
27
|
+
subject(:parsed_includes) do
|
28
|
+
described_class.parse_includes(['thingone.thingtwo.thingthree', 'thingone.thingfour', 'thingone.thingtwo.thingfive', 'thingsix.thingseven'])
|
29
|
+
end
|
30
|
+
|
31
|
+
specify { expect(parsed_includes.includes).to eq ['thingone', 'thingsix'] }
|
32
|
+
specify { expect(parsed_includes.next.includes).to eq ['thingtwo', 'thingfour', 'thingseven'] }
|
33
|
+
specify { expect(parsed_includes.next.next.includes).to eq ['thingthree', 'thingfive'] }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -29,7 +29,7 @@ RSpec.describe JsonApi::Resource do
|
|
29
29
|
describe 'relationships' do
|
30
30
|
subject(:serialized_article) do
|
31
31
|
article = Person.new('Anatoly Fyodorovich Krimov', 'red_star@kremlin.mil').articles.first
|
32
|
-
ArticleResource.new(article, include: [:author, :comments]).to_hash
|
32
|
+
ArticleResource.new(article, include: JsonApi::Includes.parse_includes([:author, :comments])).to_hash
|
33
33
|
end
|
34
34
|
|
35
35
|
context 'with a cardinality of one' do
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class BaseTestClass < JsonApi::Resource
|
4
|
+
end
|
5
|
+
|
6
|
+
describe BaseTestClass do
|
7
|
+
let!(:person) do
|
8
|
+
Person.new('Brad J. Armbruster', 'ace@airforce.mil')
|
9
|
+
end
|
10
|
+
|
11
|
+
subject(:test_class) { described_class.new(person) }
|
12
|
+
|
13
|
+
it 'provides a links hash' do
|
14
|
+
expect(test_class.links_hash).to eq({ 'self' => "http://localhost:3000/people/#{person.id}" })
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'provides a links hash' do
|
18
|
+
expect(test_class.to_hash['links']).to be_present
|
19
|
+
end
|
20
|
+
|
21
|
+
it "doesn't include links if configuration has them turned off" do
|
22
|
+
BaseTestClass.instance_variable_set(:@_use_links, false)
|
23
|
+
expect(test_class.to_hash['links']).to be_blank
|
24
|
+
end
|
25
|
+
end
|
@@ -55,11 +55,20 @@ RSpec.describe JsonApi::Resources::RelationshipMeta do
|
|
55
55
|
expect(links_object['links']['related']).to eq "http://localhost:3000/articles/#{article.uuid}/author"
|
56
56
|
end
|
57
57
|
end
|
58
|
+
|
59
|
+
context 'with links turned off' do
|
60
|
+
before { JsonApi.configuration.use_links = false }
|
61
|
+
after { JsonApi.configuration.use_links = true }
|
62
|
+
it 'returns an empty hash' do
|
63
|
+
expect(links_object['links']).to be_blank
|
64
|
+
end
|
65
|
+
end
|
58
66
|
end
|
59
67
|
|
60
68
|
describe 'data serialization' do
|
69
|
+
let(:included_data) { JsonApi::Includes.parse_includes('author') }
|
61
70
|
subject(:serialized_object) do
|
62
|
-
rel = author_relation.build_resources(parent_resource: article_resource, included:
|
71
|
+
rel = author_relation.build_resources(parent_resource: article_resource, included: included_data)
|
63
72
|
rel.to_hash
|
64
73
|
end
|
65
74
|
|
@@ -69,8 +78,9 @@ RSpec.describe JsonApi::Resources::RelationshipMeta do
|
|
69
78
|
|
70
79
|
describe 'data object' do
|
71
80
|
context 'when an array' do
|
81
|
+
let(:included_data) { JsonApi::Includes.parse_includes('comments') }
|
72
82
|
subject(:serialized_object) do
|
73
|
-
rel = comments_relation.build_resources(parent_resource: article_resource, included:
|
83
|
+
rel = comments_relation.build_resources(parent_resource: article_resource, included: included_data)
|
74
84
|
rel.to_hash
|
75
85
|
end
|
76
86
|
|
@@ -88,8 +98,9 @@ RSpec.describe JsonApi::Resources::RelationshipMeta do
|
|
88
98
|
end
|
89
99
|
|
90
100
|
describe 'identity hash' do
|
101
|
+
let(:included_data) { JsonApi::Includes.parse_includes('author') }
|
91
102
|
it 'returns an identity hash given a model and parent resource' do
|
92
|
-
rel = author_relation.build_resources(parent_resource: article_resource, included:
|
103
|
+
rel = author_relation.build_resources(parent_resource: article_resource, included: included_data)
|
93
104
|
serialized_object = rel.to_hash
|
94
105
|
expect(serialized_object['data'].keys).to eq ['id', 'type']
|
95
106
|
end
|
@@ -97,8 +108,9 @@ RSpec.describe JsonApi::Resources::RelationshipMeta do
|
|
97
108
|
|
98
109
|
describe 'relationship serialization' do
|
99
110
|
context 'when the option "include" is true' do
|
111
|
+
let(:included_data) { JsonApi::Includes.parse_includes('author') }
|
100
112
|
it 'includes the data object' do
|
101
|
-
rel = author_relation.build_resources(parent_resource: article_resource, included:
|
113
|
+
rel = author_relation.build_resources(parent_resource: article_resource, included: included_data)
|
102
114
|
serialized_data = rel.to_hash
|
103
115
|
expect(serialized_data).to include('data')
|
104
116
|
end
|
@@ -115,7 +127,7 @@ RSpec.describe JsonApi::Resources::RelationshipMeta do
|
|
115
127
|
|
116
128
|
describe 'passing in a resource class' do
|
117
129
|
let(:simple_article_resource) do
|
118
|
-
SimpleArticleResource.new(article, include: ['author', 'comments'])
|
130
|
+
SimpleArticleResource.new(article, include: JsonApi::Includes.parse_includes(['author', 'comments']))
|
119
131
|
end
|
120
132
|
|
121
133
|
let(:author_relation) do
|
@@ -36,6 +36,7 @@ RSpec.describe JsonApi::Serializer do
|
|
36
36
|
subject(:serialized) do
|
37
37
|
JsonApi.serialize(person, meta: { meta_key: 'meta value' }, include: [:articles])
|
38
38
|
end
|
39
|
+
|
39
40
|
it 'has a top level included object' do
|
40
41
|
expect(serialized['included']).to be_present
|
41
42
|
end
|
@@ -46,6 +47,14 @@ RSpec.describe JsonApi::Serializer do
|
|
46
47
|
end
|
47
48
|
expect(found_document).to be_present
|
48
49
|
end
|
50
|
+
|
51
|
+
it 'supports nested includes' do
|
52
|
+
serialized = JsonApi.serialize(person, include: ['articles.comments'])
|
53
|
+
comments = serialized['included'].select do |document|
|
54
|
+
document['type'] == 'comments'
|
55
|
+
end
|
56
|
+
expect(comments).to be_present
|
57
|
+
end
|
49
58
|
end
|
50
59
|
end
|
51
60
|
|
@@ -125,10 +125,11 @@ end
|
|
125
125
|
|
126
126
|
class CommentResource < JsonApi::Resource
|
127
127
|
id_field :uuid
|
128
|
-
attribute :author
|
129
128
|
attribute :comment_text
|
130
129
|
attribute :created_at
|
131
130
|
attribute :updated_at
|
131
|
+
|
132
|
+
has_one :author
|
132
133
|
end
|
133
134
|
|
134
135
|
# namespaced resources
|
metadata
CHANGED
@@ -1,97 +1,97 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: json_api_ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tracey Eubanks
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-02-
|
11
|
+
date: 2016-02-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '3'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '3'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - ~>
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '1.3'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - ~>
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '1.3'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - ~>
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '3'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - ~>
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '3'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rspec-its
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - ~>
|
59
|
+
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '1'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - ~>
|
66
|
+
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '1'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: pry-byebug
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - ~>
|
73
|
+
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '3'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - ~>
|
80
|
+
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '3'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: guard-rspec
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- - ~>
|
87
|
+
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '4'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- - ~>
|
94
|
+
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '4'
|
97
97
|
description: Extremely lightweight implementation of JSON API
|
@@ -101,8 +101,8 @@ executables: []
|
|
101
101
|
extensions: []
|
102
102
|
extra_rdoc_files: []
|
103
103
|
files:
|
104
|
-
- .gitignore
|
105
|
-
- .rspec
|
104
|
+
- ".gitignore"
|
105
|
+
- ".rspec"
|
106
106
|
- CHANGELOG.md
|
107
107
|
- Gemfile
|
108
108
|
- Gemfile.lock
|
@@ -114,6 +114,7 @@ files:
|
|
114
114
|
- lib/json_api_ruby/configuration.rb
|
115
115
|
- lib/json_api_ruby/error_resource.rb
|
116
116
|
- lib/json_api_ruby/exceptions.rb
|
117
|
+
- lib/json_api_ruby/includes.rb
|
117
118
|
- lib/json_api_ruby/resource.rb
|
118
119
|
- lib/json_api_ruby/resources/base.rb
|
119
120
|
- lib/json_api_ruby/resources/discovery.rb
|
@@ -121,7 +122,10 @@ files:
|
|
121
122
|
- lib/json_api_ruby/resources/relationships.rb
|
122
123
|
- lib/json_api_ruby/serializer.rb
|
123
124
|
- lib/json_api_ruby/version.rb
|
125
|
+
- spec/json_api_ruby/configuration_spec.rb
|
126
|
+
- spec/json_api_ruby/includes_spec.rb
|
124
127
|
- spec/json_api_ruby/resource_spec.rb
|
128
|
+
- spec/json_api_ruby/resources/base_spec.rb
|
125
129
|
- spec/json_api_ruby/resources/discover_spec.rb
|
126
130
|
- spec/json_api_ruby/resources/relationships_spec.rb
|
127
131
|
- spec/json_api_ruby/serializer_spec.rb
|
@@ -138,22 +142,25 @@ require_paths:
|
|
138
142
|
- lib
|
139
143
|
required_ruby_version: !ruby/object:Gem::Requirement
|
140
144
|
requirements:
|
141
|
-
- -
|
145
|
+
- - ">="
|
142
146
|
- !ruby/object:Gem::Version
|
143
147
|
version: '0'
|
144
148
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
145
149
|
requirements:
|
146
|
-
- -
|
150
|
+
- - ">="
|
147
151
|
- !ruby/object:Gem::Version
|
148
152
|
version: '0'
|
149
153
|
requirements: []
|
150
154
|
rubyforge_project:
|
151
|
-
rubygems_version: 2.
|
155
|
+
rubygems_version: 2.5.2
|
152
156
|
signing_key:
|
153
157
|
specification_version: 4
|
154
158
|
summary: Extremely lightweight implementation of JSON API
|
155
159
|
test_files:
|
160
|
+
- spec/json_api_ruby/configuration_spec.rb
|
161
|
+
- spec/json_api_ruby/includes_spec.rb
|
156
162
|
- spec/json_api_ruby/resource_spec.rb
|
163
|
+
- spec/json_api_ruby/resources/base_spec.rb
|
157
164
|
- spec/json_api_ruby/resources/discover_spec.rb
|
158
165
|
- spec/json_api_ruby/resources/relationships_spec.rb
|
159
166
|
- spec/json_api_ruby/serializer_spec.rb
|