向render方法添加include参数不能修复N + 1查询

时间:2017-07-26 23:10:50

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

我有以下型号:

class Request < ApplicationRecord
    belongs_to :contact
    belongs_to :hub_post
end

class Contact < ApplicationRecord
    has_many :requests
    has_many :likes
end

class Like < ApplicationRecord
    belongs_to :hub_post
    belongs_to :contact
end

class HubPost < ApplicationRecord
    has_many :requests
    has_many :likes
end

在我的HubPostSerializer中,我有以下方法:

def liked_by_current_contact
    scope.present? && object.likes.where(contact_id: scope.id).present?
end

在我的RequestsController中,我使用hub_postslikes抓取请求,然后返回JSON响应(我正在使用active_model_serializers 0.10.4和{{ 1}} adapter)像这样:

:json

这当然是一个明显的N + 1问题(Bullet宝石出人意料地似乎没有这个问题)。查看日志时,我可以看到每个hub_post的requests = current_contact.requests.includes(hub_post: [:contact]) # More controller code here respond_to do |format| format.json { render json: requests, each_serializer: PortalRequestSerializer, scope: current_contact } end 语句。现在我尝试包括SELECT,如此:

likes

有趣的是Bullet宝石没有在N + 1上获得,但是Scout却没有。

我也尝试根据documentation向我的render方法添加requests = current_contact.requests.includes(hub_post: [:contact, :likes]) requests = current_contact.requests.includes(hub_post: [contact: [:likes]]) 参数,如下所示:

include

我也尝试过使用单级和多级通配符,如下所示:

respond_to do |format|
    format.json { render json: requests, include: 'hub_posts,hub_posts.likes', each_serializer: PortalRequestSerializer, scope: current_contact }
end

然而我所做的一切似乎都没有消除N + 1。我不确定这是宝石如何处理嵌套序列化器中的关系或者我是否只是遗漏某些东西的问题。

更新

以下是来自服务器日志的gist查询。

2 个答案:

答案 0 :(得分:0)

在我看来,您应该从

更改includes声明
requests = current_contact.requests.includes(hub_post: [:contact])

requests = current_contact.requests.includes(:hub_post, :contact)

答案 1 :(得分:0)

我假设您的请求模型有contact_id来存储current_contact的ID,因此您可以尝试:

request = Request.where(contact_id: current_contact.id).includes(:contact, { hub_post: :likes })