diff --git a/lib/json-api-vanilla/parser.rb b/lib/json-api-vanilla/parser.rb index b24a3b9..3bb8a50 100644 --- a/lib/json-api-vanilla/parser.rb +++ b/lib/json-api-vanilla/parser.rb @@ -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 @@ -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 @@ -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) diff --git a/spec/json-api-vanilla/diff_spec.rb b/spec/json-api-vanilla/diff_spec.rb index 064d837..2ca599d 100644 --- a/spec/json-api-vanilla/diff_spec.rb +++ b/spec/json-api-vanilla/diff_spec.rb @@ -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 @@ -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 diff --git a/spec/json-api-vanilla/example.json b/spec/json-api-vanilla/example.json index 43550cd..0947c95 100644 --- a/spec/json-api-vanilla/example.json +++ b/spec/json-api-vanilla/example.json @@ -56,6 +56,17 @@ "relationships": { "author": { "data": { "type": "people", "id": "2" } + }, + "tags": { + "data": [ + { "type": "tag", "id": "42" } + ] + }, + "post": { + "data": { + "type": "post", + "id": "42" + } } }, "links": {