diff --git a/lib/jsonapi/deserializable/resource.rb b/lib/jsonapi/deserializable/resource.rb index c607576..c31ea7b 100644 --- a/lib/jsonapi/deserializable/resource.rb +++ b/lib/jsonapi/deserializable/resource.rb @@ -10,12 +10,14 @@ module JSONAPI attr_accessor :type_block, :id_block, :attr_blocks, :has_one_rel_blocks, :has_many_rel_blocks, :default_attr_block, :default_has_one_rel_block, - :default_has_many_rel_block + :default_has_many_rel_block, + :key_formatter end self.attr_blocks = {} self.has_one_rel_blocks = {} self.has_many_rel_blocks = {} + self.key_formatter = proc { |k| k } def self.inherited(klass) super @@ -27,6 +29,7 @@ module JSONAPI klass.default_attr_block = default_attr_block klass.default_has_one_rel_block = default_has_one_rel_block klass.default_has_many_rel_block = default_has_many_rel_block + klass.key_formatter = key_formatter end def self.call(payload) @@ -95,7 +98,7 @@ module JSONAPI block = self.class.attr_blocks[key] || self.class.default_attr_block return {} unless block - hash = block.call(val, key) + hash = block.call(val, self.class.key_formatter.call(key)) register_mappings(hash.keys, "/data/attributes/#{key}") hash end @@ -122,7 +125,7 @@ module JSONAPI id = val['data'] && val['data']['id'] type = val['data'] && val['data']['type'] - hash = block.call(val, id, type, key) + hash = block.call(val, id, type, self.class.key_formatter.call(key)) register_mappings(hash.keys, "/data/relationships/#{key}") hash end @@ -136,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, key) + hash = block.call(val, ids, types, self.class.key_formatter.call(key)) register_mappings(hash.keys, "/data/relationships/#{key}") hash end diff --git a/lib/jsonapi/deserializable/resource/dsl.rb b/lib/jsonapi/deserializable/resource/dsl.rb index 16d4571..ffe37fb 100644 --- a/lib/jsonapi/deserializable/resource/dsl.rb +++ b/lib/jsonapi/deserializable/resource/dsl.rb @@ -47,6 +47,10 @@ module JSONAPI self.default_has_many_rel_block = block || DEFAULT_HAS_MANY_BLOCK end end + + def key_format(callable = nil, &block) + self.key_formatter = callable || block + end end end end diff --git a/spec/resource/DSL/key_format_spec.rb b/spec/resource/DSL/key_format_spec.rb new file mode 100644 index 0000000..e1aa85e --- /dev/null +++ b/spec/resource/DSL/key_format_spec.rb @@ -0,0 +1,96 @@ +require 'spec_helper' + +describe JSONAPI::Deserializable::Resource, '.key_format' do + subject { klass.call(payload) } + + let(:payload) do + { + 'data' => { + 'type' => 'foo', + 'attributes' => { 'foo' => 'bar', 'foo-bar' => 'baz' }, + 'relationships' => { + 'baz' => { + 'data' => nil + }, + 'bar-baz' => { + 'data' => [] + } + } + } + } + end + + context 'when all fields are whitelisted' do + context 'when a key formatter is provided as a block' do + let(:klass) do + Class.new(JSONAPI::Deserializable::Resource) do + key_format { |k| k.capitalize } + attributes + has_many + has_one + end + end + + it 'formats keys accordingly' do + is_expected.to eq(Foo: 'bar', 'Foo-bar'.to_sym => 'baz', + Baz_id: nil, Baz_type: nil, + 'Bar-baz_ids'.to_sym => [], + 'Bar-baz_types'.to_sym => []) + end + end + + context 'when a key formatter is provided as a callable' do + let(:klass) do + Class.new(JSONAPI::Deserializable::Resource) do + key_format ->(k) { k.capitalize } + attributes + has_many + has_one + end + end + + it 'formats keys accordingly' do + is_expected.to eq(Foo: 'bar', 'Foo-bar'.to_sym => 'baz', + Baz_id: nil, Baz_type: nil, + 'Bar-baz_ids'.to_sym => [], + 'Bar-baz_types'.to_sym => []) + end + end + end + + context 'when certain fields are whitelisted' do + let(:klass) do + Class.new(JSONAPI::Deserializable::Resource) do + key_format { |k| k.capitalize } + attributes :foo + has_one :baz + end + end + + it 'formats keys accordingly' do + is_expected.to eq(Foo: 'bar', + Baz_id: nil, Baz_type: nil) + end + end + + context 'when inheriting' do + let(:klass) do + superclass = Class.new(JSONAPI::Deserializable::Resource) do + key_format { |k| k.capitalize } + end + + Class.new(superclass) do + attributes + has_many + has_one + end + end + + it 'formats keys accordingly' do + is_expected.to eq(Foo: 'bar', 'Foo-bar'.to_sym => 'baz', + Baz_id: nil, Baz_type: nil, + 'Bar-baz_ids'.to_sym => [], + 'Bar-baz_types'.to_sym => []) + end + end +end