如何在active_model_serializers中执行预先加载

时间:2014-05-22 18:34:58

标签: ruby-on-rails ruby-on-rails-4 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时,它有一个严重的&#34; n + 1问题&#34;并将产生数千个电话,如:

    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文档说您应该使用预先加载但不指定他们打算如何完成。是否必须在序列化程序中指定包含?如果是这样,怎么样?

1 个答案:

答案 0 :(得分:2)

这是一个很好的描述和解释。这就是你要找的东西?

class ModelName
  default_scope includes(:other)
end

How to add `:include` to default_scope?

编辑:

我没有像你这样的模型嵌套这样做,我已经通过使用序列化器的一个级别完成了这一点,并且我还使用jbuilder来缓解痛苦并通过2个级别来控制控制。我仍然相信你想把这层控制放在模型层面上。