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
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions activemodel/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
* Make `ActiveModel::Serializers::JSON#from_json` compatible with `#assign_attributes`

*Sean Doyle*

Please check [7-2-stable](https://github.com/rails/rails/blob/7-2-stable/activemodel/CHANGELOG.md) for previous changes.
8 changes: 7 additions & 1 deletion activemodel/lib/active_model/serializers/json.rb
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,13 @@ def as_json(options = nil)
def from_json(json, include_root = include_root_in_json)
hash = ActiveSupport::JSON.decode(json)
hash = hash.values.first if include_root
self.attributes = hash

if respond_to?(:assign_attributes)
assign_attributes(hash)
else
self.attributes = hash
end

self
end
end
Expand Down
20 changes: 20 additions & 0 deletions activemodel/test/cases/serializers/json_serialization_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@
require "active_support/core_ext/object/instance_variables"

class JsonSerializationTest < ActiveModel::TestCase
class CamelContact < Contact
include ActiveModel::AttributeAssignment

def assign_attributes(attributes)
super(attributes.deep_transform_keys(&:underscore))
end
end

def setup
@contact = Contact.new
@contact.name = "Konata Izumi"
Expand Down Expand Up @@ -178,6 +186,18 @@ def @contact.favorite_quote; "Constraints are liberating"; end
assert_equal result.preferences, @contact.preferences
end

test "from_json supports models that include ActiveModel::AttributeAssignment and override assign_attributes" do
serialized = @contact.as_json
serialized.deep_transform_keys! { |key| key.camelize(:lower) }
result = CamelContact.new.from_json(serialized.to_json)

assert_equal result.name, @contact.name
assert_equal result.age, @contact.age
assert_equal Time.parse(result.created_at), @contact.created_at
assert_equal result.awesome, @contact.awesome
assert_equal result.preferences, @contact.preferences
end

test "custom as_json should be honored when generating json" do
def @contact.as_json(options = nil); { name: name, created_at: created_at }; end
json = @contact.to_json
Expand Down