discourse/plugins/discourse-topic-voting/lib/discourse_topic_voting/topic_query_extension.rb
Martin Brennan 062b112e51
DEV: Improve vote queries (#39394)
The change is limited to the topic-voting voter preview and vote-list
queries.

`/voting/who` now only loads a capped preview of active voters instead
of loading every vote and mapping users in Ruby., then limiting on the
client. The cap is 104, archived votes are excluded from the preview,
and the client now uses `topic.vote_count` as the total so the popup can
show “and N more...” without fetching the full voter list.

Also tightened the two vote-list queries so archived votes no longer
appear in `state=my_votes` or `/topics/voted-by/:username`.

Finally, the vote and vote-count models now use `with_deleted` for their
topic association so soft-deleted topics can still be resolved where
those records reference them.
2026-04-21 16:10:28 +10:00

45 lines
1.5 KiB
Ruby

# frozen_string_literal: true
module DiscourseTopicVoting
TRENDING_SCORE_SQL = <<~SQL.squish
COALESCE((
SELECT SUM(1.0 / (EXTRACT(EPOCH FROM (NOW() - tv.created_at)) / 3600.0 + 2.0))
FROM topic_voting_votes tv
WHERE tv.topic_id = topics.id
), 0)
SQL
module TopicQueryExtension
def list_voted_by(user)
create_list(:user_topics) do |topics|
topics.joins(
"INNER JOIN topic_voting_votes ON topic_voting_votes.topic_id = topics.id",
).where("topic_voting_votes.user_id = ? AND topic_voting_votes.archive = FALSE", user.id)
end
end
def list_votes
create_list(:votes, unordered: true) do |topics|
topics.joins(
"LEFT JOIN topic_voting_topic_vote_count dvtvc ON dvtvc.topic_id = topics.id",
).order("COALESCE(dvtvc.votes_count,'0')::integer DESC, topics.bumped_at DESC")
end
end
def list_hot
category_id = get_category_id(@options[:category]) || @options[:category_id]
if category_id && Category.can_vote?(category_id)
create_list(:hot, unordered: true, prioritize_pinned: true) do |topics|
topics = remove_muted(topics, user, options)
topics.joins(
"LEFT JOIN topic_voting_topic_vote_count dvtvc ON dvtvc.topic_id = topics.id",
).order(
"#{DiscourseTopicVoting::TRENDING_SCORE_SQL} DESC, COALESCE(dvtvc.votes_count, 0) DESC, topics.bumped_at DESC",
)
end
else
super
end
end
end
end