Rails ActiveModel Serializer: получение глубоко вложенной ассоциации ActiveRecord

Я использую ActiveModel::Serializer для сериализации данных json. У меня есть три модели следующим образом

class Invoice < ApplicationRecord
  has_many :invoiceDetails, inverse_of: :invoice
  belongs_to :customer
  accepts_nested_attributes_for :invoiceDetails
end

class InvoiceDetail < ApplicationRecord
  belongs_to :invoice
  belongs_to :product
end

class Product < ApplicationRecord
  belongs_to :company
  belongs_to :category
  belongs_to :user
  has_many :invoice_details
end

Сериализаторы следующие:

class InvoiceSerializer < ActiveModel::Serializer
  attributes :id, :total_amount, :balance_amount, :created_at
  belongs_to :customer
  has_many :invoiceDetails
end


class InvoiceDetailSerializer < ActiveModel::Serializer
  attributes :id, :quantity
  belongs_to :product
  belongs_to :invoice
end

class ProductSerializer < ActiveModel::Serializer
  attributes :id, :name, :mrp, :sp, :cp, :stocks, :isPublished
  has_one :category
end

Когда я извлекаю счет-фактуру, я получаю атрибуты из связанной модели invoiceDetails и модели клиента, но атрибуты из модели продукта, связанной с моделью invoiceDetails, отсутствуют.

Например, если я получаю счет, это результат:

[
    {
        "id": 3,
        "total_amount": 450,
        "balance_amount": 350,
        "created_at": "2017-06-27T17:02:20.000Z",
        "customer": {
            "id": 4,
            "company_id": 1,
            "name": "vivek",
            "isActive": true,
            "created_at": "2017-06-27T14:35:50.000Z",
            "updated_at": "2017-06-27T14:35:50.000Z",
            "mobile": "12345678",
            "address": "test",
            "pan_number": null,
            "tin_number": null,
            "party_name": "vipul jwelers"
        },
        "invoiceDetails": [
            {
                "id": 4,
                "quantity": 1
            },
            {
                "id": 5,
                "quantity": 1
            }
        ]
    }
]

Однако, если я извлекаю invoiceDetail напрямую, я получаю связанные атрибуты модели.

**[
    {
        "id": 6,
        "quantity": 5,
        "product": {
            "id": 4,
            "name": "Test Prod",
            "mrp": 150,
            "sp": 130,
            "cp": 100,
            "stocks": 100,
            "isPublished": true
        },
        "invoice": {
            "id": 4,
            "total_amount": 3903,
            "balance_amount": 3,
            "created_at": "2017-07-01T07:45:02.000Z"
        }
    },
    {
        "id": 7,
        "quantity": 10,
        "product": {
            "id": 5,
            "name": "Test Prod 2",
            "mrp": 300,
            "sp": 250,
            "cp": 200,
            "stocks": 10,
            "isPublished": true
        },
        "invoice": {
            "id": 4,
            "total_amount": 3903,
            "balance_amount": 3,
            "created_at": "2017-07-01T07:45:02.000Z"
        }
    }
]**

Итак, для извлечения вложенных атрибутов непосредственно из счета-фактуры мне нужно изменить отношения между моими моделями?

Кто-нибудь сталкивался с такими же проблемами или какие-либо обходные пути, которые вы можете предложить?


comment
stackoverflow.com/ вопросы/32079897/   -  person Pavel Mikhailyuk    schedule 04.07.2017
comment
Только я могу добавить: не используйте его глобально, используйте render json: data, include: '**' там, где вам действительно нужна глубокая вложенность.   -  person Pavel Mikhailyuk    schedule 04.07.2017
comment
Спасибо, человек, который работал ..!!   -  person Paras    schedule 04.07.2017
comment
Можете ли вы добавить ответ на свой вопрос или прокомментировать здесь, что вы должны сделать для других, у которых может быть такая же проблема?   -  person Mugur 'Bud' Chirica    schedule 11.07.2017


Ответы (1)


Если кто-то застрял в этой проблеме, вот что я сделал:

Всякий раз, когда я хочу получить глубоко вложенную ассоциацию, я добавляю ключевое слово "include **" в контроллер во время ответа.

Например :

def show
    cust_id = params[:customer_id]
    invoice_id = params[:id]
    if cust_id && invoice_id
      invoice = Invoice.where(:id => invoice_id, :customer_id => cust_id)
      render json: invoice, include: '**', status: 200
    else
      render json: { errors: "Customer ID or Invoice ID is NULL" }, status: 422
    end
  end

include * * извлечет все вложенные атрибуты для модели счета, используя сериализатор, если он определен для соответствующих моделей.

person Paras    schedule 14.07.2017
comment
Не удалось отредактировать ваш ответ из-за ограничения количества символов, но, возможно, вы захотите обновить текст, чтобы он отражал include ** вместо include *, чтобы он соответствовал вашему блоку кода. - person doz87; 22.03.2018
comment
Мне пришлось удалить операторы belongs_to в сериализаторах, в других я увидел ошибку «слишком глубокий стек». - person Obromios; 30.07.2018