活动模型序列化程序:在ArraySerializer的根目录外添加额外信息

时间:2014-01-06 09:54:23

标签: ruby-on-rails ruby activemodel active-model-serializers

假设我有一个模型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响应中包含一些与任何特定用户无关的额外信息,该怎么办? E.g:

{
  "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?我无法弄清楚)。如何添加额外的根元素?

4 个答案:

答案 0 :(得分:10)

您可以将它们作为第二个参数传递给respond_with

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

在初始化程序集ActiveModel::Serializer.root = true中的0.9.3版中:

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

在控制器中

render json: @user,  meta: { total: 10 }

答案 1 :(得分:4)

使用render

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

问题是,这不会调用UserSerializer,只是在每个用户对象上调用.as_json并跳过Serializer。所以我必须明确地做到这一点:

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 :(得分:0)

如果您不想修改序列化程序或渲染,只是一个简单的黑客攻击:

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

答案 3 :(得分:0)

我能够通过在控制器中添加以下内容来使用这个用例。 AMS 0.10没有其他任何需要。

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