Сериализаторы активных моделей: добавление дополнительной информации вне корня в ArraySerializer

Скажем, у меня есть модель User и сериализатор UserSerializer < ActiveModel::Serializer, а также контроллер, который выглядит так:

class UsersController < ApplicationController
  respond_to :json
  def index
    respond_with User.all
  end
end

Теперь, если я посещу /users, я получу ответ JSON, который выглядит следующим образом:

{
  "users": [
    {
      "id": 7,
      "name": "George"
    },
    {
      "id": 8,
      "name": "Dave"
    }
    .
    .
    .
  ]
}

Но что, если я хочу включить в ответ JSON дополнительную информацию, не относящуюся ни к одному конкретному Пользователю? Например.:

{
  "time": "2014-01-06 16:52 GMT",
  "url": "http://www.example.com", 
  "noOfUsers": 2,
  "users": [
    {
      "id": 7,
      "name": "George"
    },
    {
      "id": 8,
      "name": "Dave"
    }
    .
    .
    .
  ]
}

Этот пример надуманный, но это хорошее приближение к тому, чего я хочу достичь. Возможно ли это с активными сериализаторами моделей? (Возможно, создав подкласс ActiveModel::ArraySerializer? Я не мог понять). Как добавить дополнительные корневые элементы?


person GMA    schedule 06.01.2014    source источник
comment
Попробуйте render :json => User.all Вместо response_with также посмотрите на as_json, это может быть полезно.   -  person Pramod Shinde    schedule 06.01.2014


Ответы (4)


Вы можете передать их в качестве второго аргумента для response_with

def index
 respond_with User.all, meta: {time: "2014-01-06 16:52 GMT",url: "http://www.example.com", noOfUsers: 2}
end

В версии 0.9.3 в инициализаторе установлен ActiveModel::Serializer.root = true:

ActiveSupport.on_load(:active_model_serializers) do
  # Disable for all serializers (except ArraySerializer)
  ActiveModel::Serializer.root = true
end

В контроллере

render json: @user,  meta: { total: 10 }
person junil    schedule 06.01.2014
comment
Это работает для меня на ActiveModelSerializers 0.8.1. См. github.com/rails -api/active_model_serializers/blob/0-8-stable/. Похоже, это изменилось в мастере, см. github.com /rails-api/active_model_serializers/blob/ - person aceofspades; 10.02.2014
comment
Также обратите внимание, что это только для массивов, если вам нужны метаданные в экземпляре, установите вызов #meta= в самом экземпляре сериализатора. - person aceofspades; 10.02.2014

Получил работу, используя render:

render json: {
  "time": "2014-01-06 16:52 GMT",
  "url": "http://www.example.com", 
  "noOfUsers": 2,
  "users": @users
}

Проблема в том, что это не вызывает UserSerializer, а просто вызывает .as_json для каждого отдельного пользовательского объекта и пропускает сериализатор. Поэтому мне пришлось сделать это явно:

def index
  .
  .
  .
  render json: {
    "time": "2014-01-06 16:52 GMT",
    "url": "http://www.example.com", 
    "noOfUsers": 2,
    "users": serialized_users
  }
end

def serialized_users
  ActiveModel::ArraySerializer.new(@users).as_json
end

Не самое элегантное решение, но оно работает.

person GMA    schedule 07.01.2014

Простой хак, если вы не хотите изменять ни сериализатор, ни рендеринг:

data = serializer.new(object, root: false)
# cannot modify data here since it is a serializer class
data = data.as_json
# do whatever to data as a Hash and pass the result for render
data[:extra] = 'extra stuff'
render json: data
person paradite    schedule 10.08.2017

Я смог заставить это работать для моего варианта использования, просто добавив следующее в свой контроллер. С AMS 0.10 больше ничего не нужно.

render 
    json: @user,  
    meta: {
        time: "2014-01-06 16:52 GMT", 
        url: "http://www.example.com", 
        noOfUsers: 2
    }
person Scott    schedule 28.01.2018