From 5598bb0f79fc35d4cd068ec0e18168057c6152c5 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 31 Oct 2013 16:51:57 -0200 Subject: [PATCH 1/2] Make Associations in root work with ArraySerializer Closes #414 --- lib/active_model/array_serializer.rb | 22 +++++++++++ .../action_controller/serialization_test.rb | 37 +++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/lib/active_model/array_serializer.rb b/lib/active_model/array_serializer.rb index 6e5e077e..62f6e535 100644 --- a/lib/active_model/array_serializer.rb +++ b/lib/active_model/array_serializer.rb @@ -37,5 +37,27 @@ module ActiveModel end end alias_method :serializable_object, :serializable_array + + def serializable_data + embedded_in_root_associations.merge!(super) + end + + def embedded_in_root_associations + hash = {} + @object.map do |item| + serializer_class = @each_serializer || Serializer.serializer_for(item) || DefaultSerializer + associations = serializer_class._associations + serializer = serializer_class.new(item, @options) + included_associations = serializer.filter(associations.keys) + associations.each do |(name, association)| + if included_associations.include? name + if association.embed_in_root? + hash[association.embedded_key] = serializer.serialize association + end + end + end + end + hash + end end end diff --git a/test/integration/action_controller/serialization_test.rb b/test/integration/action_controller/serialization_test.rb index c790e4a0..7ffd4c56 100644 --- a/test/integration/action_controller/serialization_test.rb +++ b/test/integration/action_controller/serialization_test.rb @@ -193,5 +193,42 @@ module ActionController assert_equal '{"my":[{"name":"Name 1","description":"Description 1"}]}', @response.body end end + + class ArrayEmbedingSerializerTest < ActionController::TestCase + def setup + super + @association = UserSerializer._associations[:profile] + @old_association = @association.dup + end + + def teardown + super + UserSerializer._associations[:profile] = @old_association + end + + class MyController < ActionController::Base + def initialize(*) + super + @user = User.new({ name: 'Name 1', email: 'mail@server.com', gender: 'M' }) + end + attr_reader :user + + def render_array_embeding_in_root + render json: [@user] + end + end + + tests MyController + + def test_render_array_embeding_in_root + @association.embed = :ids + @association.embed_in_root = true + + get :render_array_embeding_in_root + assert_equal 'application/json', @response.content_type + + assert_equal("{\"my\":[{\"name\":\"Name 1\",\"email\":\"mail@server.com\",\"profile_id\":#{@controller.user.profile.object_id}}],\"profiles\":[{\"name\":\"N1\",\"description\":\"D1\"}]}", @response.body) + end + end end end From d3d6c981487ed1cadef6247c85008a6f538270ec Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 31 Oct 2013 17:28:39 -0200 Subject: [PATCH 2/2] Make ArraySerializer reuse Serializer embedded_in_root_associations code --- lib/active_model/array_serializer.rb | 29 ++++++++++------------------ lib/active_model/serializable.rb | 12 ++++++++---- lib/active_model/serializer.rb | 4 ---- 3 files changed, 18 insertions(+), 27 deletions(-) diff --git a/lib/active_model/array_serializer.rb b/lib/active_model/array_serializer.rb index 62f6e535..157f8192 100644 --- a/lib/active_model/array_serializer.rb +++ b/lib/active_model/array_serializer.rb @@ -30,34 +30,25 @@ module ActiveModel end end + def serializer_for(item) + serializer_class = @each_serializer || Serializer.serializer_for(item) || DefaultSerializer + serializer_class.new(item, @options) + end + def serializable_array @object.map do |item| - serializer = @each_serializer || Serializer.serializer_for(item) || DefaultSerializer - serializer.new(item, @options).serializable_object + serializer_for(item).serializable_object end end alias_method :serializable_object, :serializable_array - def serializable_data - embedded_in_root_associations.merge!(super) - end - def embedded_in_root_associations - hash = {} - @object.map do |item| - serializer_class = @each_serializer || Serializer.serializer_for(item) || DefaultSerializer - associations = serializer_class._associations - serializer = serializer_class.new(item, @options) - included_associations = serializer.filter(associations.keys) - associations.each do |(name, association)| - if included_associations.include? name - if association.embed_in_root? - hash[association.embedded_key] = serializer.serialize association - end - end + @object.each_with_object({}) do |item, hash| + serializer = serializer_for(item) + if serializer.respond_to?(:embedded_in_root_associations) + hash.merge!(serializer.embedded_in_root_associations) end end - hash end end end diff --git a/lib/active_model/serializable.rb b/lib/active_model/serializable.rb index c5adb684..7a34bc04 100644 --- a/lib/active_model/serializable.rb +++ b/lib/active_model/serializable.rb @@ -11,11 +11,15 @@ module ActiveModel end def serializable_data - if respond_to?(:meta) && meta - { meta_key => meta } - else - {} + embedded_in_root_associations.tap do |hash| + if respond_to?(:meta) && meta + hash[meta_key] = meta + end end end + + def embedded_in_root_associations + {} + end end end diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index 6bdb48e5..4e215545 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -141,10 +141,6 @@ end keys end - def serializable_data - embedded_in_root_associations.merge!(super) - end - def embedded_in_root_associations associations = self.class._associations included_associations = filter(associations.keys)