Сериализаторы активной модели: добавление дополнительной информации вне корня в 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
? Я не мог понять это). Как добавить дополнительные корневые элементы?
Ответы
Ответ 1
Сработала с помощью 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
Не самое элегантное решение, но оно работает.
Ответ 2
Вы можете передать их в качестве второго аргумента для 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 }
Ответ 3
Просто простой взлом, если вы не хотите изменять сериализатор или рендеринг:
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
Ответ 4
Мне удалось заставить это работать для моего использования, просто добавив следующее в мой контроллер. Больше ничего не нужно с AMS 0.10.
render
json: @user,
meta: {
time: "2014-01-06 16:52 GMT",
url: "http://www.example.com",
noOfUsers: 2
}