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 :user
|
||||||
belongs_to :topic, counter_cache: :posts_count
|
belongs_to :topic, counter_cache: :posts_count
|
||||||
|
belongs_to :reply_to_user, class_name: "User"
|
||||||
|
|
||||||
has_many :post_replies
|
has_many :post_replies
|
||||||
has_many :replies, through: :post_replies
|
has_many :replies, through: :post_replies
|
||||||
|
@ -190,12 +191,6 @@ class Post < ActiveRecord::Base
|
||||||
(quote_count == 0) && (reply_to_post_number.present?)
|
(quote_count == 0) && (reply_to_post_number.present?)
|
||||||
end
|
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
|
def reply_notification_target
|
||||||
return if reply_to_post_number.blank?
|
return if reply_to_post_number.blank?
|
||||||
Post.where("topic_id = :topic_id AND post_number = :post_number AND user_id <> :user_id",
|
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)
|
PostRevisor.new(self).revise!(updated_by, new_raw, opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: move into PostCreator
|
||||||
# Various callbacks
|
# Various callbacks
|
||||||
before_create do
|
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.post_number ||= Topic.next_post_number(topic_id, reply_to_post_number.present?)
|
||||||
self.cooked ||= cook(raw, topic_id: topic_id)
|
self.cooked ||= cook(raw, topic_id: topic_id)
|
||||||
self.sort_order = post_number
|
self.sort_order = post_number
|
||||||
|
@ -278,6 +279,7 @@ class Post < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO: Move some of this into an asynchronous job?
|
# TODO: Move some of this into an asynchronous job?
|
||||||
|
# TODO: Move into PostCreator
|
||||||
after_create do
|
after_create do
|
||||||
# Update attributes on the topic - featured users and last posted.
|
# Update attributes on the topic - featured users and last posted.
|
||||||
attrs = {last_posted_at: created_at, last_post_user_id: user_id}
|
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)
|
admin? || TrustLevel.compare(trust_level, level)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# a touch faster than automatic
|
||||||
|
def admin?
|
||||||
|
admin
|
||||||
|
end
|
||||||
|
|
||||||
def change_trust_level(level)
|
def change_trust_level(level)
|
||||||
raise "Invalid trust level #{level}" unless TrustLevel.valid_level?(level)
|
raise "Invalid trust level #{level}" unless TrustLevel.valid_level?(level)
|
||||||
self.trust_level = TrustLevel.levels[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
|
@all_posts = @posts
|
||||||
|
|
||||||
|
|
||||||
filter_posts(options)
|
filter_posts(options)
|
||||||
|
|
||||||
@draft_key = @topic.draft_key
|
@draft_key = @topic.draft_key
|
||||||
|
@ -130,7 +131,8 @@ class TopicView
|
||||||
@max = post_number - 1
|
@max = post_number - 1
|
||||||
|
|
||||||
@posts = @posts.reverse_order.where("post_number < ?", post_number)
|
@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 = @max - @posts.size
|
||||||
@min = 1 if @min < 1
|
@min = 1 if @min < 1
|
||||||
end
|
end
|
||||||
|
@ -140,7 +142,7 @@ class TopicView
|
||||||
@initial_load = false
|
@initial_load = false
|
||||||
@min = post_number
|
@min = post_number
|
||||||
@posts = @posts.regular_order.where("post_number > ?", 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
|
@max = @min + @posts.size
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -275,7 +277,7 @@ class TopicView
|
||||||
|
|
||||||
def filter_posts_in_range(min, max)
|
def filter_posts_in_range(min, max)
|
||||||
@min, @max = 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
|
end
|
||||||
|
|
||||||
def find_topic(topic_id)
|
def find_topic(topic_id)
|
||||||
|
|
Loading…
Reference in New Issue