You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails页面加载检测到预加载缺失,无Bullet gem如何修复?

预加载缺失问题修复方案

问题描述

页面加载时触发N+1查询告警(未使用Bullet gem):

USE eager loading detected
  Notification => [:actor]
  Add to your query: .includes([:actor])
Call stack
  .../views/api/notifications/index.json.jbuilder:6

USE eager loading detected
  Notification => [:notifiable]
  Add to your query: .includes([:notifiable])
Call stack
  .../views/api/notifications/index.json.jbuilder:9

涉及代码文件

视图文件 /views/api/notifications/index.json.jbuilder

json.new_notification_count @new_notification_count
json.next_page @notifications.next_page
json.notifications do |json|
  json.array! @notifications do |notification|
    json.id notification.id
    json.actor notification.actor.username
    json.actor_avatar_img_tag avatar_of(notification.actor, size: 40)
    json.action notification.action
    json.type notification.notifiable.class.to_s.underscore.humanize.downcase
    json.url case notification.notifiable.class.to_s
              when "Post" then post_path(notification.notifiable)
              when "User" then user_path(notification.notifiable)
              when "Response" then post_path(notification.notifiable.post, anchor: "response_#{notification.notifiable.id}")
              when "Message" then conversations_path(notification.notifiable)
              when "Order" then order_path(notification.notifiable)
             end
    json.time_ago time_ago_in_words(notification.created_at) + " ago"
    json.unread notification.read_at.nil?
  end
end

控制器代码

def index
    @notifications = Notification.where(recipient: current_user)
                                 .recent.paginate(page: params[:page], per_page: 8)
    @new_notification_count = Notification.where(recipient: current_user, is_new: true).count
end

模型代码

belongs_to :recipient, class_name: "User"
belongs_to :actor, class_name: "User"
belongs_to :notifiable, polymorphic: true

scope :pristine, -> { where(is_new: true) }
scope :recent, -> { order(created_at: :desc) }
scope :unread, -> { where(read_at: nil) }

修复步骤

告警已经明确指出需要预加载actor和notifiable关联,直接在控制器的查询链中添加.includes方法即可解决N+1问题:

修改控制器的index方法,新增预加载语句:

def index
    @notifications = Notification.where(recipient: current_user)
                                 .includes(:actor, :notifiable) # 新增预加载关联
                                 .recent.paginate(page: params[:page], per_page: 8)
    @new_notification_count = Notification.where(recipient: current_user, is_new: true).count
end

可选优化

如果notifiable关联的Response模型需要访问其post关联(如视图中notification.notifiable.post),可以进一步添加嵌套预加载:

.includes(:actor, notifiable: [:post])

该优化可避免针对Response模型再次触发N+1查询,根据实际业务场景选择即可。

内容的提问来源于stack exchange,提问作者Romeo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 19:47:06