0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-08 17:53:55 +08:00
discourse/plugins/discourse-topic-voting/app/services/discourse_topic_voting/votes/remove.rb
Martin Brennan a5dca201d8
DEV: Refactor topic voting controller endpoints into services (#39312)
* Move topic vote and unvote controller logic into
`DiscourseTopicVoting::Votes::Cast` and `Remove` services
* Handle stale `topic_id` values through service result matching instead
of raising from controller logic
* Preserve archived votes by only removing active votes during unvote
* Keep webhook payloads and vote response behavior intact while
tightening mutation flow coverage
2026-04-22 08:42:20 +10:00

67 lines
1.5 KiB
Ruby
Vendored

# frozen_string_literal: true
module DiscourseTopicVoting
module Votes
class Remove
include Service::Base
params do
attribute :topic_id, :integer
validates :topic_id, presence: true
end
model :topic
policy :can_see_topic
model :active_vote, optional: true
only_if :active_vote_present? do
transaction do
step :destroy_active_vote
step :refresh_vote_count
end
step :enqueue_topic_unvote_webhook
end
private
def fetch_topic(params:)
Topic.find_by(id: params.topic_id)
end
def can_see_topic(guardian:, topic:)
guardian.can_see?(topic)
end
def fetch_active_vote(guardian:, topic:)
DiscourseTopicVoting::Vote.find_by(user: guardian.user, topic: topic, archive: false)
end
def active_vote_present?(active_vote:)
active_vote.present?
end
def destroy_active_vote(active_vote:)
active_vote.destroy!
end
def refresh_vote_count(topic:)
topic.update_vote_count
end
def enqueue_topic_unvote_webhook(guardian:, topic:)
return if !WebHook.active_web_hooks(:topic_unvote).exists?
payload = {
topic_id: topic.id,
topic_slug: topic.slug,
voter_id: guardian.user.id,
vote_count: topic.vote_count,
}
WebHook.enqueue_topic_voting_hooks(:topic_unvote, topic, payload.to_json)
end
end
end
end