From 60b5901af813f0bd075acafd952f0238ad02f1bb Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 4 Nov 2013 10:09:27 -0200 Subject: [PATCH] Don't treat has_one associations embed objects as an array Closes #442 Thanks @arrtchiu for reporing and giving a test case --- lib/active_model/serializer/associations.rb | 23 ++++++++++--------- .../active_model/serializer/has_many_test.rb | 14 ++++++++++- .../active_model/serializer/has_one_test.rb | 16 ++++++++++++- 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/lib/active_model/serializer/associations.rb b/lib/active_model/serializer/associations.rb index 3d7451a8..3858650b 100644 --- a/lib/active_model/serializer/associations.rb +++ b/lib/active_model/serializer/associations.rb @@ -19,23 +19,16 @@ module ActiveModel @key = options[:key] @embedded_key = options[:root] || name - self.serializer_class = @options[:serializer] + serializer = @options[:serializer] + @serializer_class = serializer.is_a?(String) ? serializer.constantize : serializer end - attr_reader :name, :embed_ids, :embed_objects, :serializer_class - attr_accessor :embed_in_root, :embed_key, :key, :embedded_key, :root_key, :options + attr_reader :name, :embed_ids, :embed_objects + attr_accessor :embed_in_root, :embed_key, :key, :embedded_key, :root_key, :serializer_class, :options alias embed_ids? embed_ids alias embed_objects? embed_objects alias embed_in_root? embed_in_root - def serializer_class=(serializer) - @serializer_class = serializer.is_a?(String) ? serializer.constantize : serializer - if @serializer_class && !(@serializer_class <= ArraySerializer) - @options.merge!(each_serializer: @serializer_class) - @serializer_class = ArraySerializer - end - end - def embed=(embed) @embed_ids = embed == :id || embed == :ids @embed_objects = embed == :object || embed == :objects @@ -49,6 +42,10 @@ module ActiveModel end def build_serializer(object) + if object.respond_to?(:to_ary) + @options.merge!(each_serializer: @serializer_class) + @serializer_class = ArraySerializer + end @serializer_class ||= Serializer.serializer_for(object) || DefaultSerializer @serializer_class.new(object, @options) end @@ -62,6 +59,10 @@ module ActiveModel end def build_serializer(object) + if @serializer_class && !(@serializer_class <= ArraySerializer) + @options.merge!(each_serializer: @serializer_class) + @serializer_class = ArraySerializer + end @serializer_class ||= ArraySerializer @serializer_class.new(object, @options) end diff --git a/test/unit/active_model/serializer/has_many_test.rb b/test/unit/active_model/serializer/has_many_test.rb index fc191dcb..c89e05a9 100644 --- a/test/unit/active_model/serializer/has_many_test.rb +++ b/test/unit/active_model/serializer/has_many_test.rb @@ -130,7 +130,7 @@ module ActiveModel }, @post_serializer.as_json) end - def test_associations_using_a_given_array_serializer + def test_associations_embedding_ids_using_a_given_array_serializer @association.embed = :ids @association.embed_in_root = true @association.serializer_class = Class.new(ActiveModel::ArraySerializer) do @@ -144,6 +144,18 @@ module ActiveModel comments: { my_content: ['fake'] } }, @post_serializer.as_json) end + + def test_associations_embedding_objects_using_a_given_array_serializer + @association.serializer_class = Class.new(ActiveModel::ArraySerializer) do + def serializable_object + { my_content: ['fake'] } + end + end + + assert_equal({ + 'post' => { title: 'Title 1', body: 'Body 1', comments: { my_content: ['fake'] } } + }, @post_serializer.as_json) + end end end end diff --git a/test/unit/active_model/serializer/has_one_test.rb b/test/unit/active_model/serializer/has_one_test.rb index c39d79ad..059d2646 100644 --- a/test/unit/active_model/serializer/has_one_test.rb +++ b/test/unit/active_model/serializer/has_one_test.rb @@ -116,7 +116,7 @@ module ActiveModel }, @user_serializer.as_json) end - def test_associations_using_a_given_serializer + def test_associations_embedding_ids_using_a_given_serializer @association.embed = :ids @association.embed_in_root = true @association.serializer_class = Class.new(ActiveModel::Serializer) do @@ -132,6 +132,20 @@ module ActiveModel 'profiles' => [{ name: 'fake' }] }, @user_serializer.as_json) end + + def test_associations_embedding_objects_using_a_given_serializer + @association.serializer_class = Class.new(ActiveModel::Serializer) do + def name + 'fake' + end + + attributes :name + end + + assert_equal({ + 'user' => { name: 'Name 1', email: 'mail@server.com', profile: { name: 'fake' } } + }, @user_serializer.as_json) + end end end end