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
相关产品推荐
相关产品推荐

