Question

FeedController returns an array with objects of these classes: Product, Kit and Article.

Is it possible and how with active_model_serializers apply ProductSerializer for Product, KitSerializer for Kit and ArticleSerializer for Article?

This should render something like this:

[
  { "type": "product", other fiels of Product },
  { "type": "kit", other fiels of Kit },
  { "type": "article", other fiels of Article }
]
Was it helpful?

Solution

This should work with version 0.9.0, and version 0.10.0 should probably support this out of the box when it is finally ready, but at the time of this answer, it was suggested that you not use that version (master/edge)

class MyArraySerializer < ActiveModel::ArraySerializer

  def initialize(object, options={})
    options[:each_serializer] = get_serializer_for(object)
    super(object, options)
  end

  private
  def get_serializer_for(klass)
    serializer_class_name = "#{klass.name}Serializer"
    serializer_class = serializer_class_name.safe_constantize

    if serializer_class
      serializer_class
    elsif klass.superclass
      get_serializer_for(klass.superclass)
    end
  end
end

You can modify the get_serializer_for method to better suit your needs. I used this for handling STI subclasses where my parent class had all of the attributes defined. You will however need individual serializers for each of your individual objects since the attributes will most likely vary.

Then in your controller:

render json: @my_array_of_mixed_classes, serializer: MyArraySerializer

OTHER TIPS

If this is no possible with active_model_serializers out of the box, maybe the reason is that you have a somewhat non-standard design of your API response. e.g. if I had to consume your API, would it be easy for me to deserialize your JSON response?

One way to get around this issue would therefore be to redesign your API response:

...
"products" : [ ARRAY of Product ],
"kits" : [ ARRAY of Kit ],
"articles" : [ ARRAY of Article ]
....

That would be easier to deserialize by the API consumer as well.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top