diff --git a/CHANGELOG.md b/CHANGELOG.md index 751da693..49b3aab2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ Features: - [#1791](https://github.com/rails-api/active_model_serializers/pull/1791) (@bf4, @youroff, @NullVoxPopuli) - Added `jsonapi_namespace_separator` config option. +- [#1889](https://github.com/rails-api/active_model_serializers/pull/1889) Support key transformation for Attributes adapter (@iancanderson, @danbee) Fixes: diff --git a/docs/general/configuration_options.md b/docs/general/configuration_options.md index e4ef79ae..b83399a2 100644 --- a/docs/general/configuration_options.md +++ b/docs/general/configuration_options.md @@ -46,6 +46,7 @@ Each adapter has a default key transform configured: | Adapter | Default Key Transform | |----|----| +| `Attributes` | `:unaltered` | | `Json` | `:unaltered` | | `JsonApi` | `:dash` | diff --git a/lib/active_model_serializers/adapter/attributes.rb b/lib/active_model_serializers/adapter/attributes.rb index 9ddf8516..79ca7b5f 100644 --- a/lib/active_model_serializers/adapter/attributes.rb +++ b/lib/active_model_serializers/adapter/attributes.rb @@ -4,7 +4,9 @@ module ActiveModelSerializers def serializable_hash(options = nil) options = serialization_options(options) options[:fields] ||= instance_options[:fields] - serializer.serializable_hash(instance_options, options, self) + serialized_hash = serializer.serializable_hash(instance_options, options, self) + + self.class.transform_key_casing!(serialized_hash, instance_options) end end end diff --git a/lib/active_model_serializers/key_transform.rb b/lib/active_model_serializers/key_transform.rb index 89143cee..d0e648e5 100644 --- a/lib/active_model_serializers/key_transform.rb +++ b/lib/active_model_serializers/key_transform.rb @@ -11,6 +11,7 @@ module ActiveModelSerializers # @see {https://github.com/rails/rails/blob/master/activesupport/lib/active_support/inflector/methods.rb#L66-L76 ActiveSupport::Inflector.camelize} def camel(value) case value + when Array then value.map { |item| camel(item) } when Hash then value.deep_transform_keys! { |key| camel(key) } when Symbol then camel(value.to_s).to_sym when String then value.underscore.camelize @@ -25,6 +26,7 @@ module ActiveModelSerializers # @see {https://github.com/rails/rails/blob/master/activesupport/lib/active_support/inflector/methods.rb#L66-L76 ActiveSupport::Inflector.camelize} def camel_lower(value) case value + when Array then value.map { |item| camel_lower(item) } when Hash then value.deep_transform_keys! { |key| camel_lower(key) } when Symbol then camel_lower(value.to_s).to_sym when String then value.underscore.camelize(:lower) @@ -40,6 +42,7 @@ module ActiveModelSerializers # @see {https://github.com/rails/rails/blob/master/activesupport/lib/active_support/inflector/methods.rb#L185-L187 ActiveSupport::Inflector.dasherize} def dash(value) case value + when Array then value.map { |item| dash(item) } when Hash then value.deep_transform_keys! { |key| dash(key) } when Symbol then dash(value.to_s).to_sym when String then value.underscore.dasherize @@ -55,6 +58,7 @@ module ActiveModelSerializers # @see {https://github.com/rails/rails/blob/master/activesupport/lib/active_support/inflector/methods.rb#L89-L98 ActiveSupport::Inflector.underscore} def underscore(value) case value + when Array then value.map { |item| underscore(item) } when Hash then value.deep_transform_keys! { |key| underscore(key) } when Symbol then underscore(value.to_s).to_sym when String then value.underscore diff --git a/test/active_model_serializers/key_transform_test.rb b/test/active_model_serializers/key_transform_test.rb index c25f6ca4..b4ff4d31 100644 --- a/test/active_model_serializers/key_transform_test.rb +++ b/test/active_model_serializers/key_transform_test.rb @@ -60,6 +60,14 @@ module ActiveModelSerializers { value: nil, expected: nil + }, + { + value: [ + { some_value: 'value' } + ], + expected: [ + { SomeValue: 'value' } + ] } ] scenarios.each do |s| @@ -126,6 +134,14 @@ module ActiveModelSerializers { value: nil, expected: nil + }, + { + value: [ + { some_value: 'value' } + ], + expected: [ + { someValue: 'value' } + ] } ] scenarios.each do |s| @@ -188,6 +204,14 @@ module ActiveModelSerializers { value: nil, expected: nil + }, + { + value: [ + { 'some_value' => 'value' } + ], + expected: [ + { 'some-value' => 'value' } + ] } ] scenarios.each do |s| @@ -254,6 +278,14 @@ module ActiveModelSerializers { value: nil, expected: nil + }, + { + value: [ + { 'some-value' => 'value' } + ], + expected: [ + { 'some_value' => 'value' } + ] } ] scenarios.each do |s| diff --git a/test/adapter/attributes_test.rb b/test/adapter/attributes_test.rb new file mode 100644 index 00000000..dee0c775 --- /dev/null +++ b/test/adapter/attributes_test.rb @@ -0,0 +1,43 @@ +require 'test_helper' + +module ActiveModelSerializers + module Adapter + class AttributesTest < ActiveSupport::TestCase + class Person + include ActiveModel::Model + include ActiveModel::Serialization + + attr_accessor :first_name, :last_name + end + + class PersonSerializer < ActiveModel::Serializer + attributes :first_name, :last_name + end + + def setup + ActionController::Base.cache_store.clear + end + + def test_serializable_hash + person = Person.new(first_name: 'Arthur', last_name: 'Dent') + serializer = PersonSerializer.new(person) + adapter = ActiveModelSerializers::Adapter::Attributes.new(serializer) + + assert_equal({ first_name: 'Arthur', last_name: 'Dent' }, + adapter.serializable_hash) + end + + def test_serializable_hash_with_transform_key_casing + person = Person.new(first_name: 'Arthur', last_name: 'Dent') + serializer = PersonSerializer.new(person) + adapter = ActiveModelSerializers::Adapter::Attributes.new( + serializer, + key_transform: :camel_lower + ) + + assert_equal({ firstName: 'Arthur', lastName: 'Dent' }, + adapter.serializable_hash) + end + end + end +end