Question

I've add the active model serializer gem to a project and it broke a bunch of stuff, one of our apis has a very specific format that I need to keep, unfortunately it doesn't appear that I can get the legacy behavior.

#Models
class Parent < ActiveRecord::Base
  attr_accessable, :id, :name, :options
  has_many :children
end

class Child < ActiveRecord::Base
  attr_accessable, :id, :name
end

#Controller
class ParentsController < ApplicationController

  respond_to :json

  def index
    #Was
    @parents = Parent.all
    respond_with @parents, :include => [:children]

    #Is (and is not working)
    @parents = Parent.includes(:children)
    respond_with @parents, each_serializer: ::ParentsSerializer, root: false  #Not working
  end
...
end

#Serializer
class ParentSerializer < ActiveModel::Serializer
  attrs = Parent.column_names.map(&:to_sym) - [:options]
  attributes(*attrs)
  has_many :children

  def filter(keys)
    keys.delete :children unless object.association(:children).loaded?
    keys.add :options
    keys
  end
end

Desired Output

[
  {
    "parent": {
      "id": 1,
      "name": "Uncle",
      "options":"Childless, LotsOfLoot",
      "children": []
    }
  },
  {
    "parent": {
      "id": 2,
      "name": "Mom",
      "options":"<3 Gossip, SoccerMom",
      "children": [
        {
          "child": {
            "id": 10,
            "name": "susy"
          }
        },
        {
          "child": {
            "id": 11,
            "name": "bobby"
          }
        }
      ]
    }
  }
]

What I need is the json to be formatted in such a way that it doesn't include the top root but does include the child roots... I know I could go with something like Rabl, but If there is a an easy clean way to do this with ActiveModel Serializers, that would be better.

Was it helpful?

Solution

To my surprise there appears to be no direct support for this, and I got lost figuring out what you'd override to add it. However the workaround isn't bad - just define a custom children method:

#Serializer
class ParentSerializer < ActiveModel::Serializer
  attrs = Parent.column_names.map(&:to_sym) - [:options]
  attributes(*attrs)
  has_many :children

  def filter(keys)
    keys.delete :children unless object.association(:children).loaded?
    keys.add :options
    keys
  end

  def children
    object.children.collect{|c| ChildSerializer.new(c, scope).as_json(root: :child)}
  end
end

You're doing the work of ArraySerializer in the children method, but I'm not sure of a cleaner way without support from AM::S.

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