You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ActiveModel::Serializer中将二级关联的嵌套哈希上移一级?

在Ruby on Rails中调整ActiveModel::Serializer的嵌套结构

我有如下ActiveRecord关联模型:

关联模型代码

class Driver
  has_one :car
  delegate :tires, to: :car
end
class Car
  belongs_to :driver
  has_many   :tires
end
class Tire
  belongs_to :car
end

原序列化器实现

使用嵌套的序列化器结构:

class DriverSerializer < ActiveModel::Serializer
  attributes :id, :name

  has_one :car

  class CarSerializer < ActiveModel::Serializer
    attributes :id

    has_many :tires

    class TireSerializer < ActiveModel::Serializer
      attributes :id
    end
  end
end

原输出JSON结构

生成的JSON中tires嵌套在car节点下:

{
  "id": 1,
  "name": "Bob",
  "car": {
    "id": 1,
    "tires": [
      {
        "id": 1
      },
      {
        "id": 2
      }
      ...
    ]
  }
}

需求

希望将tires字段上移一级,直接嵌套在driver节点下,且要复用现有定义的序列化器,不想用Ruby的map方法手动实例化序列化器对象。已知可以通过自定义属性方法实现,但想找更简洁的方式。

解决方案

可以直接在DriverSerializer中添加has_many :tires,并指定复用已定义的TireSerializer:

class DriverSerializer < ActiveModel::Serializer
  attributes :id, :name

  # 若不需要返回car节点,可删除此行
  has_one :car

  # 直接关联tires,复用嵌套的TireSerializer
  has_many :tires, serializer: CarSerializer::TireSerializer
end

调整后生成的JSON结构:

{
  "id": 1,
  "name": "Bob",
  "car": {
    "id": 1
  },
  "tires": [
    {
      "id": 1
    },
    {
      "id": 2
    }
    ...
  ]
}

原理是Driver模型已经通过delegate :tires, to: :car实现了tires方法,ActiveModel::Serializer会自动调用该方法获取数据,配合指定已有的序列化器,无需手动用map处理,完美复用现有代码。

内容的提问来源于stack exchange,提问作者Starscream512

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 10:57:32