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

Make ActiveModel::Serializers::JSON#from_json compatible with #assign_attributes #51781

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

seanpdoyle
Copy link
Contributor

@seanpdoyle seanpdoyle commented May 10, 2024

Motivation / Background

Prior to this commit, models that inherit from
ActiveModel::AttributeAssignment (either directly or through including ActiveModel::API) lose their ability to override the attribute assignment utilized during calls to
ActiveModel::Serializers::JSON#from_json.

Incidentally, #from_json calls #attributes= (instead of #assign_attributes), whereas models that inherit from ActiveModel::AttributeAssignment have #attributes= automatically aliased to #assign_attributes.

This has two unintended side effects:

  1. calls to #from_json will never invoke #assign_attributes overrides, since they invoke #attributes= directly

  2. overrides to #assign_attributes won't have any effects on #attributes=, since that alias is defined on the original implementation

Detail

This commit attempts to remedy that issue by attempting to call #assign_attributes first before falling back to #attributes=.

Additional information

A change-free solution would be to encourage (through documentation) a corresponding alias :attributes= assign_attributes line any time models override assign_attributes.

Alternatively, the ActiveModel::AttributeAssignment#assign_attributes method could be defined as #attributes= instead (with a complementary alias assign_attributes attributes= call). This is likely a backwards-incompatible change.

Checklist

Before submitting the PR make sure the following are checked:

  • This Pull Request is related to one change. Unrelated changes should be opened in separate PRs.
  • Commit message has a detailed description of what changed and why. If this PR fixes a related issue include it in the commit message. Ex: [Fix #issue-number]
  • Tests are added or updated if you fix a bug or add a feature.
  • CHANGELOG files are updated for the changed libraries if there is a behavior change or additional feature. Minor bug fixes and documentation changes should not be included.

…ign_attributes`

Prior to this commit, models that inherit from
[ActiveModel::AttributeAssignment][] (either directly or through
including [ActiveModel::API][]) lose their ability to override the
attribute assignment utilized during calls to
[ActiveModel::Serializers::JSON#from_json][].

Incidentally, `#from_json` calls `#attributes=` (instead of
`#assign_attributes`), whereas models that inherit from
`ActiveModel::AttributeAssignment` have `#attributes=` [automatically
aliased to `#assign_attributes`][alias].

This has two unintended side effects:

1. calls to `#from_json` will never invoke `#assign_attributes`
   overrides, since they invoke `#attributes=` directly

2. overrides to `#assign_attributes` won't have any effects on
   `#attributes=`, since that alias is defined on the original
   implementation

This commit attempts to remedy that issue by attempting to call
`#assign_attributes` first before falling back to `#attributes=`.

A change-free solution would be to encourage (through documentation) a
corresponding `alias :attributes= assign_attributes` line any time
models override `assign_attributes`.

[ActiveModel::AttributeAssignment]: https://edgeapi.rubyonrails.org/classes/ActiveModel/AttributeAssignment.html
[ActiveModel::API]: https://edgeapi.rubyonrails.org/classes/ActiveModel/API.html
[ActiveModel::Serializers::JSON#from_json]: https://edgeapi.rubyonrails.org/classes/ActiveModel/Serializers/JSON.html#method-i-from_json
[alias]: https://github.com/rails/rails/blob/be0cb4e8f9aa0b105ddd035061202a5d23491b5a/activemodel/lib/active_model/attribute_assignment.rb#L37
@seanpdoyle seanpdoyle force-pushed the from-json-assign-attributes branch from f60b140 to 01c6cda Compare May 16, 2024 17:16
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

1 participant