diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index 26749f1a..fca53cb7 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -80,6 +80,10 @@ module ActiveModel options[:key] || name end + def polymorphic? + options[:polymorphic] + end + protected def find_serializable(object, scope, context, options) @@ -115,11 +119,34 @@ module ActiveModel class HasOne < Config #:nodoc: def serialize(object, scope, context, options) - { key => object && find_serializable(object, scope, context, options).as_json(:root => false) } + if polymorphic? + if object + find_serializable(object, scope, context, options).as_json(:root => polymorphic_key(object)) + else + {} + end + else + { key => object && find_serializable(object, scope, context, options).as_json(:root => false) } + end end + def serialize_ids(object, scope) - { key => object && object.read_attribute_for_serialization(:id) } + if polymorphic? && object + { + polymorphic_key(object) => object.read_attribute_for_serialization(:id), + } + elsif polymorphic? && !object + { } + elsif object + { key => object.read_attribute_for_serialization(:id) } + else + { key => nil } + end + end + + def polymorphic_key(object) + object.class.to_s.demodulize.underscore.to_sym end end end diff --git a/test/serializer_test.rb b/test/serializer_test.rb index 838e6a1a..72b1b7a0 100644 --- a/test/serializer_test.rb +++ b/test/serializer_test.rb @@ -652,6 +652,95 @@ class SerializerTest < ActiveModel::TestCase }, hash.as_json) end + class PolymorphicUser < User ; end + + class PolymorphicUserSerializer < ActiveModel::Serializer + attributes :first_name, :last_name + end + + def test_polymorphic_has_one + polymorphic_blog = Class.new do + attr_accessor :writer + end + + polymorphic_serializer = Class.new(ActiveModel::Serializer) do + has_one :writer, :polymorphic => true + end + + user = PolymorphicUser.new + blog = polymorphic_blog.new + blog.writer = user + + serializer = polymorphic_serializer.new(blog, user) + + assert_equal({ + :polymorphic_user => { + :first_name => "Jose", + :last_name => "Valim" + } + }, serializer.as_json) + end + + def test_polymorphic_has_one_with_nil + polymorphic_blog = Class.new do + attr_accessor :writer + end + + polymorphic_serializer = Class.new(ActiveModel::Serializer) do + has_one :writer, :polymorphic => true + end + + user = PolymorphicUser.new + blog = polymorphic_blog.new + blog.writer = nil + + serializer = polymorphic_serializer.new(blog, user) + + assert_equal({ + }, serializer.as_json) + end + + def test_polymorphic_has_one_with_ids + polymorphic_blog = Class.new do + attr_accessor :writer + end + + polymorphic_serializer = Class.new(ActiveModel::Serializer) do + embed :ids + has_one :writer, :polymorphic => true + end + + user = PolymorphicUser.new :id => 1 + blog = polymorphic_blog.new + blog.writer = user + + serializer = polymorphic_serializer.new(blog, user) + + assert_equal({ + :polymorphic_user => 1 + }, serializer.as_json) + end + + def test_polymorphic_has_one_id_with_nil + polymorphic_blog = Class.new do + attr_accessor :writer + end + + polymorphic_serializer = Class.new(ActiveModel::Serializer) do + embed :ids + has_one :writer, :polymorphic => true + end + + user = PolymorphicUser.new + blog = polymorphic_blog.new + blog.writer = nil + + serializer = polymorphic_serializer.new(blog, user) + + assert_equal({ + }, serializer.as_json) + end + def test_root_provided_in_options author_serializer = Class.new(ActiveModel::Serializer) do attributes :id, :name