Active Model Serializers, без корня массива, но дочерние корни

Я добавил гем сериализатора активной модели в проект, и он сломал кучу вещей, один из наших API имеет очень специфический формат, который мне нужно сохранить, к сожалению, похоже, что я не могу получить устаревшее поведение.

#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

Желаемый результат

[
  {
    "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"
          }
        }
      ]
    }
  }
]

Мне нужно, чтобы json был отформатирован таким образом, чтобы он не включал верхний корень, но включал дочерние корни... Я знаю, что мог бы пойти с чем-то вроде Rabl, но если есть простой чистый способ сделать это с помощью сериализаторов ActiveModel, это было бы лучше.


person Intentss    schedule 05.05.2014    source источник


Ответы (1)


К моему удивлению, похоже, что для этого нет прямой поддержки, и я потерялся, выясняя, что вы переопределите, чтобы добавить это. Однако обходной путь неплох — просто определите собственный метод children:

#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

Вы выполняете работу ArraySerializer в методе children, но я не уверен в более чистом способе без поддержки AM::S.

person Dave S.    schedule 06.05.2014
comment
В итоге я использовал rabl для настройки вывода... Я предполагаю, что это тоже сработает. - person Intentss; 06.06.2014
comment
У меня работало с active_model_serializer 0.8.1, но пришлось немного изменить его: атрибуты :children ChildSerializer.new(c, scope: scope).as_json(root: c.class.name.underscore) - person jogaco; 18.07.2014