How to set a custom ArraySerialize for the entire application

302 views
Skip to first unread message

Simone Carletti

unread,
Jan 8, 2014, 9:25:16 AM1/8/14
to rails-a...@googlegroups.com
I recently switched our API to ActiveModel::Serializer (initially 0.8.0, today I upgraded to 0.9.0.alpha1) but I had to maintain the compatibility with our existing API response format.
Our API was configure to inject the root name by default, and in Rails 3.0 this was generating the following result in case of an array of resources

[{ "model" : { foo: 1, bar: 2 }}, "model" : { foo: 2, bar: 2 }, etc]

This is quite different than what the ArraySerializer will generate when you force the root element. For this reason, I created a custom ArraySerializer called RootArraySerializer with the following implementation

class RootArraySerializer < ActiveModel::ArraySerializer
  self.root = false

  def serializable_object
    @object.map do |item|
      serializer = serializer_for(item)
      { serializer.class.root_name => serializer.serializable_object }
    end
  end
end

So far so good. However, I can't find a way to configure ActiveModel::Serializer to use this serializer as default instead of an ArraySerializer. I tried configuring a default :each_serializer using the `default_serializer_options`, but this caused the class to be used for every single resource, because the option takes precedence over the Serializer.serializer_for

serializer_class = @each_serializer || Serializer.serializer_for(item) || DefaultSerializer

Is this behavior expected? In this case, what's the best way to change that default? Would you accept a patch in case?

The best solution I found so far is to monkey-patch ActiveModel::Serializer::serializer_for to return the custom serializer if the resource responds to `to_ary`, but I believe there should be a better way.

Any idea? 

Thanks,
-- Simone

Reply all
Reply to author
Forward
0 new messages