Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support key transformation for Attributes adapter #1889

Conversation

iancanderson
Copy link
Contributor

Purpose

The :attributes adapter is the default one, but it did not support
key transformation. This was very surprising behavior, since the
"Configuration Options" page in the guides didn't mention that this
behavior was not supported by the attributes adapter.

Changes

This PR adds key transform support to the attributes adapter, and
adds documentation about the default transform for the attributes
adapter (which is :unaltered).

Caveats

This could potentially break existing apps that have a key_transform set that also use the Attributes adapter. Before this change, the key_transform setting would be a no-op. After this change, the key_transform would take effect and therefore change the behavior of their current apps.

However, the current behavior seems like a bug to me, and I think it is worth fixing.

@mention-bot
Copy link

@iancanderson, thanks for your PR! By analyzing the annotation information on this pull request, we identified @bf4, @remear and @NullVoxPopuli to be potential reviewers

@@ -46,6 +46,13 @@ def arguments_passed_in?
end
end

class Person < Model
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you move these to your test file?

We really don't like the poros file, as it makes deugging tests a little more convoluted than it should be

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed! I'll move them

@NullVoxPopuli
Copy link
Contributor

Looks good, can you add a changelog entry?

@iancanderson iancanderson force-pushed the ia-db-add-key-transform-to-attributes-adapter branch from 5a848d7 to f971b6b Compare August 24, 2016 18:08
@iancanderson
Copy link
Contributor Author

@NullVoxPopuli thanks for the quick reply! I added a changelog entry, moved the model definition into the test, and squashed 👍

@iancanderson
Copy link
Contributor Author

@NullVoxPopuli I'm having trouble actually using this in practice - hold off on merging for now

@bf4
Copy link
Member

bf4 commented Aug 24, 2016

@iancanderson This is a feature you want?

@bf4
Copy link
Member

bf4 commented Aug 24, 2016

The 'Attributes' adapter is probably going to go away. I've already moved most of it back into the Serializer itself. Then the JSON adapter will simply support a :root option just like ActiveModel::Serializers::JSON in Rails does (and probably therefore also support ActiveRecord::Base.include_root_in_json = true, etc.)

@iancanderson
Copy link
Contributor Author

@bf4 What we need is an adapter that can serialize without a JSON root that can also transform keys.

See the most recent commit that handles the issue we had with the first approach. I'll comment in-line as well to point out where the problem was.

@@ -4,7 +4,9 @@ class Attributes < Base
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)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem was that since there is no root key for the Attributes adapter, this serialized_hash could actually be an array, which was not handled by the KeyTransform functions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(This happens when a CollectionSerializer is used, which maps the resources into an array)

@iancanderson
Copy link
Contributor Author

@bf4 I understand that the attributes adapter is "going away", but it's currently the default serializer. Until it's gone, (and until the json adapter gets an option to not include the root), I think this patch is worthwhile.

The changes made in KeyTransform to support an array would also be necessary for the json adapter to support payloads without a root key, so I think this PR is actually a stepping stone to what you eventually want. What do you think?

@@ -11,6 +11,7 @@ module KeyTransform
# @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) }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This really should have been here the whole time anyway. Welcome change!

@bf4 do you know if there is much of performance improvement that could be made be re-ordering these? or would it not be worth it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a separate feature that should be noted in the changelog, I think. Otherwise, LGTM

@iancanderson
Copy link
Contributor Author

@NullVoxPopuli @bf4 anything I can do to move this forward?

@NullVoxPopuli
Copy link
Contributor

@iancanderson can you move your changelog entry to be under the features heading?

The `:attributes` adapter is the default one, but it did not support
key transformation. This was very surprising behavior, since the
"Configuration Options" page in the guides didn't mention that this
behavior was not supported by the attributes adapter.

This commit adds key transform support to the attributes adapter, and
adds documentation about the default transform for the attributes
adapter (which is `:unaltered`).

This commit also handles arrays when transforming keys, which was needed
in the case where you're serializing a collection with the Attributes
adapter. With the JSON adapter, it was always guaranteed to pass a hash
to the KeyTransform functions because of the top-level key. Since there
is no top-level key for the Attributes adapter, the return value could
be an array.
@iancanderson iancanderson force-pushed the ia-db-add-key-transform-to-attributes-adapter branch from 37db347 to 20e91fa Compare August 25, 2016 17:46
@iancanderson
Copy link
Contributor Author

@NullVoxPopuli changelog moved, and squashed the commits in 20e91fa

@NullVoxPopuli
Copy link
Contributor

woo!

@NullVoxPopuli NullVoxPopuli merged commit 2423ca4 into rails-api:master Aug 25, 2016
@iancanderson iancanderson deleted the ia-db-add-key-transform-to-attributes-adapter branch August 25, 2016 19:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants