diff --git a/lib/jsonapi/deserializable/resource.rb b/lib/jsonapi/deserializable/resource.rb index 8312358..c46e4ad 100644 --- a/lib/jsonapi/deserializable/resource.rb +++ b/lib/jsonapi/deserializable/resource.rb @@ -35,9 +35,9 @@ module JSONAPI new(payload).to_h end - def initialize(payload) - @document = payload - @data = @document['data'] || {} + def initialize(payload, root: '/data') + @data = payload || {} + @root = root @type = @data['type'] @id = @data['id'] @attributes = @data['attributes'] || {} @@ -58,7 +58,7 @@ module JSONAPI def register_mappings(keys, path) keys.each do |k| - @reverse_mapping[k] = path + @reverse_mapping[k] = @root + path end end @@ -74,7 +74,7 @@ module JSONAPI return {} unless block hash = block.call(@type) - register_mappings(hash.keys, '/data/type') + register_mappings(hash.keys, '/type') hash end @@ -83,7 +83,7 @@ module JSONAPI return {} unless @id && block hash = block.call(@id) - register_mappings(hash.keys, '/data/id') + register_mappings(hash.keys, '/id') hash end @@ -98,7 +98,7 @@ module JSONAPI return {} unless block hash = block.call(val, self.class.key_formatter.call(key)) - register_mappings(hash.keys, "/data/attributes/#{key}") + register_mappings(hash.keys, "/attributes/#{key}") hash end @@ -125,7 +125,7 @@ module JSONAPI id = val['data'] && val['data']['id'] type = val['data'] && val['data']['type'] hash = block.call(val, id, type, self.class.key_formatter.call(key)) - register_mappings(hash.keys, "/data/relationships/#{key}") + register_mappings(hash.keys, "/relationships/#{key}") hash end # rubocop: enable Metrics/AbcSize @@ -139,7 +139,7 @@ module JSONAPI ids = val['data'].map { |ri| ri['id'] } types = val['data'].map { |ri| ri['type'] } hash = block.call(val, ids, types, self.class.key_formatter.call(key)) - register_mappings(hash.keys, "/data/relationships/#{key}") + register_mappings(hash.keys, "/relationships/#{key}") hash end # rubocop: enable Metrics/AbcSize diff --git a/spec/resource/DSL/attribute_spec.rb b/spec/resource/DSL/attribute_spec.rb index 002bf51..1be6fa1 100644 --- a/spec/resource/DSL/attribute_spec.rb +++ b/spec/resource/DSL/attribute_spec.rb @@ -5,10 +5,8 @@ describe JSONAPI::Deserializable::Resource, '.attribute' do context 'when a block is specified' do it 'creates corresponding field' do payload = { - 'data' => { - 'type' => 'foo', - 'attributes' => { 'foo' => 'bar' } - } + 'type' => 'foo', + 'attributes' => { 'foo' => 'bar' } } klass = Class.new(JSONAPI::Deserializable::Resource) do attribute(:foo) { |foo| Hash[foo: foo] } @@ -23,10 +21,8 @@ describe JSONAPI::Deserializable::Resource, '.attribute' do context 'when no block is specified' do it 'defaults to creating a field with same name' do payload = { - 'data' => { - 'type' => 'foo', - 'attributes' => { 'foo' => 'bar' } - } + 'type' => 'foo', + 'attributes' => { 'foo' => 'bar' } } klass = Class.new(JSONAPI::Deserializable::Resource) do attribute(:foo) @@ -41,7 +37,7 @@ describe JSONAPI::Deserializable::Resource, '.attribute' do context 'when attribute is absent' do it 'does not create corresponding field if attribute is absent' do - payload = { 'data' => { 'type' => 'foo', 'attributes' => {} } } + payload = { 'type' => 'foo', 'attributes' => {} } klass = Class.new(JSONAPI::Deserializable::Resource) do attribute(:foo) { |foo| Hash[foo: foo] } end @@ -54,7 +50,7 @@ describe JSONAPI::Deserializable::Resource, '.attribute' do context 'when attributes member is absent' do it 'does not create corresponding field if no attribute specified' do - payload = { 'data' => { 'type' => 'foo' } } + payload = { 'type' => 'foo' } klass = Class.new(JSONAPI::Deserializable::Resource) do attribute(:foo) { |foo| Hash[foo: foo] } end diff --git a/spec/resource/DSL/attributes_spec.rb b/spec/resource/DSL/attributes_spec.rb index d7ab563..e35e254 100644 --- a/spec/resource/DSL/attributes_spec.rb +++ b/spec/resource/DSL/attributes_spec.rb @@ -5,10 +5,8 @@ describe JSONAPI::Deserializable::Resource, '.attributes' do context 'when no keys are specified' do it 'defaults to creating fields with same name' do payload = { - 'data' => { - 'type' => 'foo', - 'attributes' => { 'foo' => 'bar', 'baz' => 'foo' } - } + 'type' => 'foo', + 'attributes' => { 'foo' => 'bar', 'baz' => 'foo' } } klass = Class.new(JSONAPI::Deserializable::Resource) do attributes @@ -23,10 +21,8 @@ describe JSONAPI::Deserializable::Resource, '.attributes' do context 'when keys are specified' do it 'creates fields with same name for whitelisted attributes' do payload = { - 'data' => { - 'type' => 'foo', - 'attributes' => { 'foo' => 'bar', 'baz' => 'foo', 'bar' => 'foo' } - } + 'type' => 'foo', + 'attributes' => { 'foo' => 'bar', 'baz' => 'foo', 'bar' => 'foo' } } klass = Class.new(JSONAPI::Deserializable::Resource) do attributes :foo, :baz @@ -43,10 +39,8 @@ describe JSONAPI::Deserializable::Resource, '.attributes' do context 'when no keys are specified' do it 'defaults to creating fields with same name' do payload = { - 'data' => { - 'type' => 'foo', - 'attributes' => { 'foo' => 'bar', 'baz' => 'foo' } - } + 'type' => 'foo', + 'attributes' => { 'foo' => 'bar', 'baz' => 'foo' } } klass = Class.new(JSONAPI::Deserializable::Resource) do attributes do |val, key| @@ -63,10 +57,8 @@ describe JSONAPI::Deserializable::Resource, '.attributes' do context 'when keys are specified' do it 'creates customized fields for whitelisted attributes' do payload = { - 'data' => { - 'type' => 'foo', - 'attributes' => { 'foo' => 'bar', 'baz' => 'foo', 'bar' => 'foo' } - } + 'type' => 'foo', + 'attributes' => { 'foo' => 'bar', 'baz' => 'foo', 'bar' => 'foo' } } klass = Class.new(JSONAPI::Deserializable::Resource) do attributes(:foo, :baz) do |val, key| diff --git a/spec/resource/DSL/has_many_spec.rb b/spec/resource/DSL/has_many_spec.rb index 9b581ae..0ff42a2 100644 --- a/spec/resource/DSL/has_many_spec.rb +++ b/spec/resource/DSL/has_many_spec.rb @@ -12,15 +12,13 @@ describe JSONAPI::Deserializable::Resource, '.has_many' do context 'relationship is not empty' do let(:payload) do { - 'data' => { - 'type' => 'foo', - 'relationships' => { - 'foo' => { - 'data' => [ - { 'type' => 'foo', 'id' => 'bar' }, - { 'type' => 'foo', 'id' => 'baz' } - ] - } + 'type' => 'foo', + 'relationships' => { + 'foo' => { + 'data' => [ + { 'type' => 'foo', 'id' => 'bar' }, + { 'type' => 'foo', 'id' => 'baz' } + ] } } } @@ -29,7 +27,7 @@ describe JSONAPI::Deserializable::Resource, '.has_many' do it 'creates corresponding fields' do actual = deserializable_foo.call(payload) expected = { foo_ids: %w(bar baz), foo_types: %w(foo foo), - foo_rel: payload['data']['relationships']['foo'] } + foo_rel: payload['relationships']['foo'] } expect(actual).to eq(expected) end @@ -48,18 +46,16 @@ describe JSONAPI::Deserializable::Resource, '.has_many' do context 'relationship is empty' do it 'creates corresponding fields' do payload = { - 'data' => { - 'type' => 'foo', - 'relationships' => { - 'foo' => { - 'data' => [] - } + 'type' => 'foo', + 'relationships' => { + 'foo' => { + 'data' => [] } } } actual = deserializable_foo.call(payload) expected = { foo_ids: [], foo_types: [], - foo_rel: payload['data']['relationships']['foo'] } + foo_rel: payload['relationships']['foo'] } expect(actual).to eq(expected) end @@ -68,10 +64,8 @@ describe JSONAPI::Deserializable::Resource, '.has_many' do context 'relationship is absent' do it 'does not create corresponding fields' do payload = { - 'data' => { - 'type' => 'foo', - 'relationships' => {} - } + 'type' => 'foo', + 'relationships' => {} } actual = deserializable_foo.call(payload) expected = {} @@ -82,11 +76,7 @@ describe JSONAPI::Deserializable::Resource, '.has_many' do context 'there is no relationships member' do it 'does not create corresponding fields' do - payload = { - 'data' => { - 'type' => 'foo' - } - } + payload = { 'type' => 'foo' } actual = deserializable_foo.call(payload) expected = {} diff --git a/spec/resource/DSL/has_one_spec.rb b/spec/resource/DSL/has_one_spec.rb index aad4efb..0956d83 100644 --- a/spec/resource/DSL/has_one_spec.rb +++ b/spec/resource/DSL/has_one_spec.rb @@ -12,12 +12,10 @@ describe JSONAPI::Deserializable::Resource, '.has_one' do context 'relationship is not nil' do let(:payload) do { - 'data' => { - 'type' => 'foo', - 'relationships' => { - 'foo' => { - 'data' => { 'type' => 'foo', 'id' => 'bar' } - } + 'type' => 'foo', + 'relationships' => { + 'foo' => { + 'data' => { 'type' => 'foo', 'id' => 'bar' } } } } @@ -26,7 +24,7 @@ describe JSONAPI::Deserializable::Resource, '.has_one' do it 'creates corresponding fields' do actual = deserializable_foo.call(payload) expected = { foo_id: 'bar', foo_type: 'foo', - foo_rel: payload['data']['relationships']['foo'] } + foo_rel: payload['relationships']['foo'] } expect(actual).to eq(expected) end @@ -45,19 +43,17 @@ describe JSONAPI::Deserializable::Resource, '.has_one' do context 'relationship value is nil' do it 'creates corresponding fields' do payload = { - 'data' => { - 'type' => 'foo', - 'relationships' => { - 'foo' => { - 'data' => nil - } + 'type' => 'foo', + 'relationships' => { + 'foo' => { + 'data' => nil } } } actual = deserializable_foo.call(payload) expected = { foo_id: nil, foo_type: nil, - foo_rel: payload['data']['relationships']['foo'] } + foo_rel: payload['relationships']['foo'] } expect(actual).to eq(expected) end @@ -66,10 +62,8 @@ describe JSONAPI::Deserializable::Resource, '.has_one' do context 'relationship is absent' do it 'does not create corresponding fields' do payload = { - 'data' => { - 'type' => 'foo', - 'relationships' => {} - } + 'type' => 'foo', + 'relationships' => {} } actual = deserializable_foo.call(payload) expected = {} @@ -80,11 +74,7 @@ describe JSONAPI::Deserializable::Resource, '.has_one' do context 'there is no relationships member' do it 'does not create corresponding fields' do - payload = { - 'data' => { - 'type' => 'foo' - } - } + payload = { 'type' => 'foo' } actual = deserializable_foo.call(payload) expected = {} diff --git a/spec/resource/DSL/id_spec.rb b/spec/resource/DSL/id_spec.rb index 4025a24..219eefb 100644 --- a/spec/resource/DSL/id_spec.rb +++ b/spec/resource/DSL/id_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe JSONAPI::Deserializable::Resource, '.id' do it 'creates corresponding field if id is present' do - payload = { 'data' => { 'type' => 'foo', 'id' => 'bar' } } + payload = { 'type' => 'foo', 'id' => 'bar' } klass = Class.new(JSONAPI::Deserializable::Resource) do id { |i| Hash[id: i] } end @@ -13,7 +13,7 @@ describe JSONAPI::Deserializable::Resource, '.id' do end it 'does not create corresponding field if id is absent' do - payload = { 'data' => { 'type' => 'foo' } } + payload = { 'type' => 'foo' } klass = Class.new(JSONAPI::Deserializable::Resource) do id { |i| Hash[id: i] } end @@ -24,7 +24,7 @@ describe JSONAPI::Deserializable::Resource, '.id' do end it 'defaults to creating an id field' do - payload = { 'data' => { 'type' => 'foo', 'id' => 'bar' } } + payload = { 'type' => 'foo', 'id' => 'bar' } klass = Class.new(JSONAPI::Deserializable::Resource) do id end diff --git a/spec/resource/DSL/key_format_spec.rb b/spec/resource/DSL/key_format_spec.rb index e1aa85e..144a68a 100644 --- a/spec/resource/DSL/key_format_spec.rb +++ b/spec/resource/DSL/key_format_spec.rb @@ -5,16 +5,14 @@ describe JSONAPI::Deserializable::Resource, '.key_format' do let(:payload) do { - 'data' => { - 'type' => 'foo', - 'attributes' => { 'foo' => 'bar', 'foo-bar' => 'baz' }, - 'relationships' => { - 'baz' => { - 'data' => nil - }, - 'bar-baz' => { - 'data' => [] - } + 'type' => 'foo', + 'attributes' => { 'foo' => 'bar', 'foo-bar' => 'baz' }, + 'relationships' => { + 'baz' => { + 'data' => nil + }, + 'bar-baz' => { + 'data' => [] } } } diff --git a/spec/resource/DSL/type_spec.rb b/spec/resource/DSL/type_spec.rb index c8a31f5..10d44c1 100644 --- a/spec/resource/DSL/type_spec.rb +++ b/spec/resource/DSL/type_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe JSONAPI::Deserializable::Resource, '.type' do it 'creates corresponding field' do - payload = { 'data' => { 'type' => 'foo' } } + payload = { 'type' => 'foo' } klass = Class.new(JSONAPI::Deserializable::Resource) do type { |t| Hash[type: t] } end @@ -13,7 +13,7 @@ describe JSONAPI::Deserializable::Resource, '.type' do end it 'defaults to creating a type field' do - payload = { 'data' => { 'type' => 'foo' } } + payload = { 'type' => 'foo' } klass = Class.new(JSONAPI::Deserializable::Resource) do type end diff --git a/spec/resource/reverse_mapping_spec.rb b/spec/resource/reverse_mapping_spec.rb index f106a5a..7947931 100644 --- a/spec/resource/reverse_mapping_spec.rb +++ b/spec/resource/reverse_mapping_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe JSONAPI::Deserializable::Resource, '#reverse_mapping' do it 'generates reverse mapping for default type' do - payload = { 'data' => { 'type' => 'foo' } } + payload = { 'type' => 'foo' } klass = Class.new(JSONAPI::Deserializable::Resource) do type end @@ -13,7 +13,7 @@ describe JSONAPI::Deserializable::Resource, '#reverse_mapping' do end it 'generates reverse mapping for overriden type' do - payload = { 'data' => { 'type' => 'foo' } } + payload = { 'type' => 'foo' } klass = Class.new(JSONAPI::Deserializable::Resource) do type { |t| { custom_type: t } } end @@ -24,7 +24,7 @@ describe JSONAPI::Deserializable::Resource, '#reverse_mapping' do end it 'generates reverse mapping for default id' do - payload = { 'data' => { 'type' => 'foo', 'id' => 'bar' } } + payload = { 'type' => 'foo', 'id' => 'bar' } klass = Class.new(JSONAPI::Deserializable::Resource) do id end @@ -35,7 +35,7 @@ describe JSONAPI::Deserializable::Resource, '#reverse_mapping' do end it 'generates reverse mapping for overriden id' do - payload = { 'data' => { 'type' => 'foo', 'id' => 'bar' } } + payload = { 'type' => 'foo', 'id' => 'bar' } klass = Class.new(JSONAPI::Deserializable::Resource) do id { |i| { custom_id: i } } end @@ -47,12 +47,10 @@ describe JSONAPI::Deserializable::Resource, '#reverse_mapping' do it 'generates reverse mapping for default attributes' do payload = { - 'data' => { - 'type' => 'foo', - 'attributes' => { - 'foo' => 'bar', - 'baz' => 'fiz' - } + 'type' => 'foo', + 'attributes' => { + 'foo' => 'bar', + 'baz' => 'fiz' } } klass = Class.new(JSONAPI::Deserializable::Resource) do @@ -67,12 +65,10 @@ describe JSONAPI::Deserializable::Resource, '#reverse_mapping' do it 'generates reverse mapping for locally overriden attributes' do payload = { - 'data' => { - 'type' => 'foo', - 'attributes' => { - 'foo' => 'bar', - 'baz' => 'fiz' - } + 'type' => 'foo', + 'attributes' => { + 'foo' => 'bar', + 'baz' => 'fiz' } } klass = Class.new(JSONAPI::Deserializable::Resource) do @@ -86,12 +82,10 @@ describe JSONAPI::Deserializable::Resource, '#reverse_mapping' do it 'generates reverse mapping for globally overriden attributes' do payload = { - 'data' => { - 'type' => 'foo', - 'attributes' => { - 'foo' => 'bar', - 'baz' => 'fiz' - } + 'type' => 'foo', + 'attributes' => { + 'foo' => 'bar', + 'baz' => 'fiz' } } klass = Class.new(JSONAPI::Deserializable::Resource) do @@ -109,15 +103,13 @@ describe JSONAPI::Deserializable::Resource, '#reverse_mapping' do it 'generates reverse mapping for default has_one' do payload = { - 'data' => { - 'type' => 'foo', - 'relationships' => { - 'foo' => { - 'data' => nil - }, - 'baz' => { - 'data' => nil - } + 'type' => 'foo', + 'relationships' => { + 'foo' => { + 'data' => nil + }, + 'baz' => { + 'data' => nil } } } @@ -135,15 +127,13 @@ describe JSONAPI::Deserializable::Resource, '#reverse_mapping' do it 'generates reverse mapping for overriden has_one' do payload = { - 'data' => { - 'type' => 'foo', - 'relationships' => { - 'foo' => { - 'data' => nil - }, - 'baz' => { - 'data' => nil - } + 'type' => 'foo', + 'relationships' => { + 'foo' => { + 'data' => nil + }, + 'baz' => { + 'data' => nil } } } @@ -169,15 +159,13 @@ describe JSONAPI::Deserializable::Resource, '#reverse_mapping' do it 'generates reverse mapping for default has_many' do payload = { - 'data' => { - 'type' => 'foo', - 'relationships' => { - 'foo' => { - 'data' => [] - }, - 'baz' => { - 'data' => [] - } + 'type' => 'foo', + 'relationships' => { + 'foo' => { + 'data' => [] + }, + 'baz' => { + 'data' => [] } } } @@ -195,15 +183,13 @@ describe JSONAPI::Deserializable::Resource, '#reverse_mapping' do it 'generates reverse mapping for overriden has_many' do payload = { - 'data' => { - 'type' => 'foo', - 'relationships' => { - 'foo' => { - 'data' => [] - }, - 'baz' => { - 'data' => [] - } + 'type' => 'foo', + 'relationships' => { + 'foo' => { + 'data' => [] + }, + 'baz' => { + 'data' => [] } } }