cache reply_to_user_id in post to eliminate a very nasty n+1 query
This commit is contained in:
parent
ec948dc660
commit
2a047df4f1
|
@ -19,6 +19,7 @@ class Post < ActiveRecord::Base
|
|||
|
||||
belongs_to :user
|
||||
belongs_to :topic, counter_cache: :posts_count
|
||||
belongs_to :reply_to_user, class_name: "User"
|
||||
|
||||
has_many :post_replies
|
||||
has_many :replies, through: :post_replies
|
||||
|
@ -190,12 +191,6 @@ class Post < ActiveRecord::Base
|
|||
(quote_count == 0) && (reply_to_post_number.present?)
|
||||
end
|
||||
|
||||
# Get the post that we reply to.
|
||||
def reply_to_user
|
||||
return if reply_to_post_number.blank?
|
||||
Post.where(topic_id: topic_id, post_number: reply_to_post_number).first.try(:user)
|
||||
end
|
||||
|
||||
def reply_notification_target
|
||||
return if reply_to_post_number.blank?
|
||||
Post.where("topic_id = :topic_id AND post_number = :post_number AND user_id <> :user_id",
|
||||
|
@ -268,8 +263,14 @@ class Post < ActiveRecord::Base
|
|||
PostRevisor.new(self).revise!(updated_by, new_raw, opts)
|
||||
end
|
||||
|
||||
|
||||
# TODO: move into PostCreator
|
||||
# Various callbacks
|
||||
before_create do
|
||||
if reply_to_post_number.present?
|
||||
self.reply_to_user_id ||= Post.select(:user_id).where(topic_id: topic_id, post_number: reply_to_post_number).first.try(:user_id)
|
||||
end
|
||||
|
||||
self.post_number ||= Topic.next_post_number(topic_id, reply_to_post_number.present?)
|
||||
self.cooked ||= cook(raw, topic_id: topic_id)
|
||||
self.sort_order = post_number
|
||||
|
@ -278,6 +279,7 @@ class Post < ActiveRecord::Base
|
|||
end
|
||||
|
||||
# TODO: Move some of this into an asynchronous job?
|
||||
# TODO: Move into PostCreator
|
||||
after_create do
|
||||
# Update attributes on the topic - featured users and last posted.
|
||||
attrs = {last_posted_at: created_at, last_post_user_id: user_id}
|
||||
|
|
|
@ -402,6 +402,11 @@ class User < ActiveRecord::Base
|
|||
admin? || TrustLevel.compare(trust_level, level)
|
||||
end
|
||||
|
||||
# a touch faster than automatic
|
||||
def admin?
|
||||
admin
|
||||
end
|
||||
|
||||
def change_trust_level(level)
|
||||
raise "Invalid trust level #{level}" unless TrustLevel.valid_level?(level)
|
||||
self.trust_level = TrustLevel.levels[level]
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
class AddReplyToUserIdToPost < ActiveRecord::Migration
|
||||
def up
|
||||
# caching this column makes the topic page WAY faster
|
||||
add_column :posts, :reply_to_user_id, :integer
|
||||
execute 'UPDATE posts p SET reply_to_user_id = (
|
||||
SELECT u.id from users u
|
||||
JOIN posts p2 ON p2.user_id = u.id AND
|
||||
p2.post_number = p.reply_to_post_number AND
|
||||
p2.topic_id = p.topic_id
|
||||
)'
|
||||
end
|
||||
|
||||
def down
|
||||
remove_column :posts, :reply_to_user_id
|
||||
end
|
||||
end
|
|
@ -34,6 +34,7 @@ class TopicView
|
|||
|
||||
@all_posts = @posts
|
||||
|
||||
|
||||
filter_posts(options)
|
||||
|
||||
@draft_key = @topic.draft_key
|
||||
|
@ -130,7 +131,8 @@ class TopicView
|
|||
@max = post_number - 1
|
||||
|
||||
@posts = @posts.reverse_order.where("post_number < ?", post_number)
|
||||
@posts = @posts.includes(:topic).joins(:user).limit(SiteSetting.posts_per_page)
|
||||
|
||||
@posts = @posts.includes(:reply_to_user).includes(:topic).joins(:user).limit(SiteSetting.posts_per_page)
|
||||
@min = @max - @posts.size
|
||||
@min = 1 if @min < 1
|
||||
end
|
||||
|
@ -140,7 +142,7 @@ class TopicView
|
|||
@initial_load = false
|
||||
@min = post_number
|
||||
@posts = @posts.regular_order.where("post_number > ?", post_number)
|
||||
@posts = @posts.includes(:topic).joins(:user).limit(SiteSetting.posts_per_page)
|
||||
@posts = @posts.includes(:reply_to_user).includes(:topic).joins(:user).limit(SiteSetting.posts_per_page)
|
||||
@max = @min + @posts.size
|
||||
end
|
||||
|
||||
|
@ -275,7 +277,7 @@ class TopicView
|
|||
|
||||
def filter_posts_in_range(min, max)
|
||||
@min, @max = min, max
|
||||
@posts = @posts.where("post_number between ? and ?", @min, @max).includes(:user).regular_order
|
||||
@posts = @posts.where("post_number between ? and ?", @min, @max).includes(:user).includes(:reply_to_user).regular_order
|
||||
end
|
||||
|
||||
def find_topic(topic_id)
|
||||
|
|
Loading…
Reference in New Issue