Как выполнить активную загрузку в active_model_serializers

У меня есть модель с несколькими слоями вложенных ассоциаций. например.,

ModelA has_many: model_b
ModelB has_one : model_c
ModelC has_many: model_d
ModelD has_many: model_e
  ...

В сериализаторах embed :ids, include: true используется для боковой загрузки:

class ModelASerializer < ActiveModel::Serializer
    embed :ids, include: true

    has_many: model_b

    attributes: ...
end

class ModelBSerializer < ActiveModel::Serializer
    embed :ids, include: true
    ...

При рендеринге model_a возникает серьезная «проблема n+1» и генерируются тысячи вызовов, например:

    ModelC Load (0.3ms)  SELECT "model_cs".* FROM "model_cs" WHERE "model_cs"."id" = $1 LIMIT 1  [["id", "2060c506-8c9c-4d1c-a64c-62455fa18bc4"]]
    CACHE (0.0ms)  SELECT "model_ds".* FROM "model_ds" WHERE "model_ds"."id" = $1 LIMIT 1  [["id", "2e36f19f-25e1-4953-99ba-f8c0271106dd"]]
    CACHE (0.0ms)  SELECT "model_es".* FROM "model_es" WHERE "model_es"."id" = $1 LIMIT 1  [["id", "31e53b55-6df6-44cd-98ad-2011cced1e1a"]]

Даже если включения указаны явно, это, похоже, не имеет эффекта:

render json: ModelA.includes(:model_bs => [:model_c =>[:model_ds => [:model_es]]])

В документации active_model_serializers говорится, что вы должны использовать нетерпеливую загрузку, но не указывает, как они намереваются это сделать. Должны ли включения указываться в сериализаторе? Если да, то как?


person Purrell    schedule 22.05.2014    source источник


Ответы (1)


Это хорошее описание и объяснение. Это то, что вы ищете?

class ModelName
  default_scope includes(:other)
end

Как добавить `:include` в default_scope?

Редактировать:

Я не делал этого в наборе моделей, как у вас, я сделал это на одном уровне, используя сериализаторы, и я также использовал jbuilder, чтобы облегчить боль и усилить контроль через 2 уровня. Я все еще верю, что вы хотите поместить этот уровень контроля на уровень модели.

person Jeff Ancel    schedule 22.05.2014