【问题标题】:How to serialize relational models as JSON in Ruby on Rails?如何在 Ruby on Rails 中将关系模型序列化为 JSON?
【发布时间】:2020-04-05 20:13:43
【问题描述】:

假设我有一个基本的User 模型:

# Name                          | Type               | Attributes
# ----------------------------- | ------------------ | ---------------------------
# **`id`**                      | `bigint`           | `not null, primary key`
# **`email`**                   | `string`           | `default(""), not null`
# **`encrypted_password`**      | `string`           | `default(""), not null`

一个用户可以拥有许多他们管理的公司。所以user.rb 包含:

has_many :company_permissions

has_many :companies, -> { distinct }, through: :company_permissions

Company 非常简单:

# Name               | Type               | Attributes
# ------------------ | ------------------ | ---------------------------
# **`id`**           | `bigint`           | `not null, primary key`
# **`description`**  | `text`             |
# **`name`**         | `string`           |

UserCompany 通过称为 CompanyPermission 的 Rails 关系模型关联:

# Name              | Type               | Attributes
# ----------------- | ------------------ | ---------------------------
# **`id`**          | `bigint`           | `not null, primary key`
# **`name`**        | `string`           |
# **`company_id`**  | `bigint`           | `not null`
# **`user_id`**     | `bigint`           | `not null`

权限的name 可以是readwritedelete。如果用户拥有超过 1 个权限(例如读取和写入),则有 2 个关系模型。

用户可以看到他们当前公司的 JSON 响应:

class CredentialsController < AuthorizedController
  def me
    render json: current_user, include: %i[companies]
  end
end

这会产生如下输出:

{
    "id": 676,
    "email": "email1@example.com",
    "companies": [{
        "id": 786,
        "name": "Some Company",
        "description": "Some Company Description"
    }]
}

如您所见,用户不知道他们拥有哪些权限。我想在此处包含来自CustomerPermission.name 的信息,可能类似于:

{
    "id": 676,
    "email": "email1@example.com",
    "companies": [{
        "id": 786,
        "name": "Some Company",
        "description": "Some Company Description",
        "permissions": ["read", "write"] # <------- I want this
    }]
}

我需要为此从头开始写ActiveModel::Serializer 吗?或者有没有其他方法可以轻松地在 JSON 输出中包含关系模型中的这个细节?

【问题讨论】:

  • 你好!你可以使用github.com/Netflix/fast_jsonapi,它很容易让它工作,而且它比主动模型序列化器工作得快得多
  • 可以不用AMS吗?当然是。只需遍历记录并设置公司属性或在获取记录时选择数组聚合。它会比只使用 AMS 更容易吗?不,可能不是。

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


【解决方案1】:

您可以使用上面评论中提到的 Alex 使用 github.com/Netflix/fast_jsonapi 来执行此操作。

请记住,这确实会更改结构以遵守Google's JSON:API standard。一切都将嵌套在“属性”属性中。当您使用 include 方法时,它不会包含来自例如 Companies 的所有数据 - 仅包含 id。

本质上,您需要创建一个自定义方法并违反标准才能实现这一点,但在我的情况下,这样做完全有道理,而不是进行多次 API 调用。

为您的 User 和 Company 模型创建一个序列化程序,您可以在其中定义一个自定义属性块,例如:

# app/serializers/user_serializer.rb
class UserSerializer
  include FastJsonapi::ObjectSerializer

  attribute :companies do |user|
    CompanySerializer.new(user.companies).serializable_hash[:data]
  end
end

# app/serializers/company_serializer.rb
class CompanySerializer
  include FastJsonapi::ObjectSerializer

  attribute :permissions do |company|
    company.company_permissions.map{|perm| perm.name}
  end
end

希望有帮助:)

【讨论】:

    猜你喜欢
    • 2023-03-13
    • 2011-07-05
    • 1970-01-01
    • 2019-04-16
    • 2018-04-05
    • 2011-10-05
    • 2010-10-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多