Eager-load comment user data (#14902)

* Eager-load comment user data

Profiles and user settings are loaded for on each comment author. On
posts with many comments, this invokes a *lot* of DB queries. This
commit replaces 2 queries per comment with 2 queries for all comments.

* Fix where I misunderstood limit's purpose

This implementation is too clever. It looks like it should just be
getting all but the last, but it uses the fact that the default is 0 to
default to getting all of them. This isn't readily understandable to
someone reading the code.

I don't have a suggestion to fix it yet so I'm just going to leave it
as-is for now.
This commit is contained in:
Jamie Gaskins 2021-10-05 04:05:01 -04:00 committed by GitHub
parent 322f7f4b16
commit 5d5dbaca95
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 6 additions and 2 deletions

View file

@ -91,7 +91,11 @@ class Comment < ApplicationRecord
alias touch_by_reaction save
def self.tree_for(commentable, limit = 0)
commentable.comments.includes(:user).arrange(order: "score DESC").to_a[0..limit - 1].to_h
commentable.comments
.includes(user: %i[setting profile])
.arrange(order: "score DESC")
.to_a[0..limit - 1]
.to_h
end
def search_id

View file

@ -124,7 +124,7 @@
<div class="comments" id="comment-trees-container">
<% if @root_comment.present? %>
<% cache ["comment_root-view-root_#{user_signed_in?}", @root_comment] do %>
<%= tree_for(@root_comment, @root_comment.subtree.includes(:user).arrange[@root_comment], @commentable) %>
<%= tree_for(@root_comment, @root_comment.subtree.includes(user: %i[setting profile]).arrange[@root_comment], @commentable) %>
<% end %>
<% else %>
<% Comment.tree_for(@commentable).each do |comment, sub_comments| %>