【发布时间】:2017-07-26 23:10:49
【问题描述】:
我有以下型号:
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_posts 和likes 获取请求,然后返回JSON 响应(我使用active_model_serializers 0.10.4 和:json 适配器),如下所示:
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
这当然是一个明显的 N+1 问题(令人惊讶的是,Bullet gem 似乎并没有意识到这一点)。查看日志时,我可以看到每个 hub_post 的 SELECT 语句。现在我尝试像这样包含likes:
requests = current_contact.requests.includes(hub_post: [:contact, :likes])
requests = current_contact.requests.includes(hub_post: [contact: [:likes]])
有趣的是,Bullet gem 不支持 N+1,但 Scout 可以。
我还尝试按照documentation 在我的渲染方法中添加一个include 参数,如下所示:
respond_to do |format|
format.json { render json: requests, include: 'hub_posts,hub_posts.likes', each_serializer: PortalRequestSerializer, scope: current_contact }
end
我也尝试过像这样使用单级和多级通配符:
respond_to do |format|
format.json { render json: requests, include: '*', each_serializer: PortalRequestSerializer, scope: current_contact }
end
respond_to do |format|
format.json { render json: requests, include: '**', each_serializer: PortalRequestSerializer, scope: current_contact }
end
但我所做的一切似乎都没有消除 N+1。我不确定这是否是 gem 如何处理嵌套序列化程序中包含的关系的问题,或者我只是遗漏了一些东西。
更新
这是来自服务器日志的查询的gist。
【问题讨论】:
标签: ruby-on-rails active-model-serializers