Как сериализовать реляционные модели как JSON в Ruby на Rails? - PullRequest
1 голос
/ 05 апреля 2020

Скажем, у меня есть базовая c 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`           |

User и Company связаны реляционной моделью Rails под названием CompanyPermission:

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

Разрешение name может быть read, write или delete. Если у пользователя есть более одного разрешения (например, на чтение и запись), то существует 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?

1 Ответ

0 голосов
/ 06 апреля 2020

Вы можете сделать это, используя github.com / Netflix / fast_jsonapi , как Алекс упомянул в комментарии выше.

Имейте в виду, это меняет структуру, чтобы придерживаться Google JSON: стандарт API . Все будет вложено в свойство «атрибуты». И когда вы используете метод include, он не будет включать в себя все данные, например, от компаний - только идентификатор.

По сути, вам нужно создать собственный метод и нарушить стандарт, чтобы достигните этого, но в моих ситуациях имело смысл делать это, а не делать несколько вызовов 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

Надеюсь, что поможет:)

...