diff --git a/lib/active_model/array_serializer.rb b/lib/active_model/array_serializer.rb index 8c050770..fe985e8b 100644 --- a/lib/active_model/array_serializer.rb +++ b/lib/active_model/array_serializer.rb @@ -15,6 +15,7 @@ module ActiveModel @object = object @scope = options[:scope] @root = options.fetch(:root, self.class._root) + @polymorphic = options.fetch(:polymorphic, false) @meta_key = options[:meta_key] || :meta @meta = options[@meta_key] @each_serializer = options[:each_serializer] @@ -33,7 +34,7 @@ module ActiveModel def serializer_for(item) serializer_class = @each_serializer || Serializer.serializer_for(item) || DefaultSerializer - serializer_class.new(item, scope: scope, key_format: key_format, only: @only, except: @except) + serializer_class.new(item, scope: scope, key_format: key_format, only: @only, except: @except, polymorphic: @polymorphic) end def serializable_object diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index f9c7e0b8..abb1162d 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -130,6 +130,7 @@ end @object = object @scope = options[:scope] @root = options.fetch(:root, self.class._root) + @polymorphic = options.fetch(:polymorphic, false) @meta_key = options[:meta_key] || :meta @meta = options[@meta_key] @wrap_in_array = options[:_wrap_in_array] @@ -138,7 +139,7 @@ end @key_format = options[:key_format] @context = options[:context] end - attr_accessor :object, :scope, :root, :meta_key, :meta, :key_format, :context + attr_accessor :object, :scope, :root, :meta_key, :meta, :key_format, :context, :polymorphic def json_key key = if root == true || root.nil? @@ -225,9 +226,9 @@ end def serialize_ids(association) associated_data = send(association.name) if associated_data.respond_to?(:to_ary) - associated_data.map { |elem| elem.read_attribute_for_serialization(association.embed_key) } + associated_data.map { |elem| serialize_id(elem, association) } else - associated_data.read_attribute_for_serialization(association.embed_key) if associated_data + serialize_id(associated_data, association) if associated_data end end @@ -260,9 +261,19 @@ end hash = attributes hash.merge! associations hash = convert_keys(hash) if key_format.present? + hash = { :type => type_name(@object), type_name(@object) => hash } if @polymorphic @wrap_in_array ? [hash] : hash end alias_method :serializable_hash, :serializable_object + + def serialize_id(elem, association) + id = elem.read_attribute_for_serialization(association.embed_key) + association.polymorphic? ? { id: id, type: type_name(elem) } : id + end + + def type_name(elem) + elem.class.to_s.demodulize.underscore.to_sym + end end end diff --git a/lib/active_model/serializer/association.rb b/lib/active_model/serializer/association.rb index cdfe9195..f62c982f 100644 --- a/lib/active_model/serializer/association.rb +++ b/lib/active_model/serializer/association.rb @@ -15,6 +15,7 @@ module ActiveModel @name = name.to_s @options = options self.embed = options.fetch(:embed) { CONFIG.embed } + @polymorphic = options.fetch(:polymorphic, false) @embed_in_root = options.fetch(:embed_in_root) { options.fetch(:include) { CONFIG.embed_in_root } } @key_format = options.fetch(:key_format) { CONFIG.key_format } @embed_key = options[:embed_key] || :id @@ -27,13 +28,14 @@ module ActiveModel @serializer_from_options = serializer.is_a?(String) ? serializer.constantize : serializer end - attr_reader :name, :embed_ids, :embed_objects + attr_reader :name, :embed_ids, :embed_objects, :polymorphic attr_accessor :embed_in_root, :embed_key, :key, :embedded_key, :root_key, :serializer_from_options, :options, :key_format, :embed_in_root_key, :embed_namespace alias embed_ids? embed_ids alias embed_objects? embed_objects alias embed_in_root? embed_in_root alias embed_in_root_key? embed_in_root_key alias embed_namespace? embed_namespace + alias polymorphic? polymorphic def embed=(embed) @embed_ids = embed == :id || embed == :ids