Skip to content

Commit

Permalink
Fix relationships of included objects (#8)
Browse files Browse the repository at this point in the history
* Fix parsing of objects that are only in relationships of included

If an object was present only in the relationships of an included object
and not in the root of the data object or the included object it was not
being parsed correctly.

* Make original_keys in prepare_object optional

* Add spec for prepare_object method

* Invoke prepare_class method only when it is needed
  • Loading branch information
matheussilvasantos authored and bazay committed Jan 6, 2020
1 parent 465553e commit 708adfb
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 9 deletions.
37 changes: 28 additions & 9 deletions lib/json-api-vanilla/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,12 @@ def self.build(hash)

obj_hashes.each do |o_hash|
klass = prepare_class(o_hash, superclass, container)
obj = klass.new
obj.type = o_hash['type']
obj.id = o_hash['id']
if o_hash['attributes']
o_hash['attributes'].each do |key, value|
set_key(obj, key, value, original_keys)
end
end
obj = prepare_object(o_hash, klass, original_keys)

if o_hash['links']
links[obj] = o_hash['links']
end

objects[[obj.type, obj.id]] = obj
end

Expand All @@ -82,10 +77,22 @@ def self.build(hash)
if data.is_a?(Array)
# One-to-many relationship.
ref = data.map do |ref_hash|
objects[[ref_hash['type'], ref_hash['id']]]
_ref = objects[[ref_hash['type'], ref_hash['id']]]

if _ref.nil?
klass = prepare_class(ref_hash, superclass, container)
_ref = prepare_object(ref_hash, klass)
end

_ref
end
else
ref = objects[[data['type'], data['id']]]

if ref.nil?
klass = prepare_class(data, superclass, container)
ref = prepare_object(data, klass)
end
end
end

Expand Down Expand Up @@ -130,6 +137,18 @@ def self.prepare_class(hash, superclass, container)
klass
end

def self.prepare_object(hash, klass, original_keys = {})
(klass.new).tap do |obj|
obj.type = hash['type']
obj.id = hash['id']
if hash['attributes']
hash['attributes'].each do |key, value|
set_key(obj, key, value, original_keys)
end
end
end
end

def self.generate_object(ruby_name, superclass, container)
klass = Class.new(superclass)
container.const_set(ruby_name, klass)
Expand Down
28 changes: 28 additions & 0 deletions spec/json-api-vanilla/diff_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@
expect(doc.links[doc.data]['self']).to eql("http://example.com/articles")
end

it "should read objects that are only in relationships of included" do
expect(doc.data.first.comments.first.post.id).to eql("42")
end

it "should read objects that are only in relationships of included when it is an array" do
expect(doc.data.first.comments.first.tags[0].id).to eql("42")
end

it "should find objects by type and id" do
expect(doc.find('comments', '5').body).to eql("First!")
end
Expand Down Expand Up @@ -114,4 +122,24 @@ class TestClasses
end
end
end

describe '.prepare_object' do
let(:data) do
{
'type' => 'example',
'id' => '1',
'attributes' => {
'name' => 'example name'
}
}
end
let(:klass) { described_class.prepare_class(data, Class.new, Module.new) }
subject { described_class.prepare_object(data, klass) }

it 'creates an object with the attributes mapped' do
expect(subject.type).to eql(data['type'])
expect(subject.id).to eql(data['id'])
expect(subject.name).to eql(data['attributes']['name'])
end
end
end
11 changes: 11 additions & 0 deletions spec/json-api-vanilla/example.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,17 @@
"relationships": {
"author": {
"data": { "type": "people", "id": "2" }
},
"tags": {
"data": [
{ "type": "tag", "id": "42" }
]
},
"post": {
"data": {
"type": "post",
"id": "42"
}
}
},
"links": {
Expand Down

0 comments on commit 708adfb

Please sign in to comment.