discourse/plugins/discourse-topic-voting/lib/discourse_topic_voting/topic_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

55 lines
1.6 KiB
Ruby

# frozen_string_literal: true
module DiscourseTopicVoting
module TopicExtension
extend ActiveSupport::Concern
prepended do
has_one :topic_vote_count,
class_name: "DiscourseTopicVoting::TopicVoteCount",
dependent: :destroy
has_many :votes, class_name: "DiscourseTopicVoting::Vote", dependent: :destroy
attribute :current_user_voted
end
def can_vote?
@can_vote ||=
SiteSetting.topic_voting_enabled && regular? && Category.can_vote?(category_id) &&
category && category.topic_id != id
end
def vote_count
self.topic_vote_count&.votes_count.to_i
end
def user_voted?(user)
if self.current_user_voted
self.current_user_voted == 1
else
votes.map(&:user_id).include?(user.id)
end
end
def update_vote_count
count = self.votes.count
DB.exec(<<~SQL, topic_id: self.id, votes_count: count)
INSERT INTO topic_voting_topic_vote_count
(topic_id, votes_count, created_at, updated_at)
VALUES
(:topic_id, :votes_count, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
ON CONFLICT (topic_id) DO UPDATE SET
votes_count = :votes_count,
updated_at = CURRENT_TIMESTAMP
WHERE topic_voting_topic_vote_count.topic_id = :topic_id
SQL
end
def who_voted(limit: DiscourseTopicVoting::VOTER_PREVIEW_LIMIT)
return if !SiteSetting.topic_voting_show_who_voted
votes.active.includes(:user).order(created_at: :desc).limit(limit).filter_map(&:user)
end
end
end