Add task to delete duplicate voters

Note that, since poll answers belong to a user and not to a voter, we
aren't doing anything regarding poll answers. This is a separate topic
that might be dealt with in a separate pull request.

Also note that, since there are no records belonging to poll voters, and
poll voters don't use `acts_as_paranoia` and don't have any callbacks on
destroy, it doesn't really matter whether we call `destroy!` or
`delete`. We're using `delete` so there are no unintended side-effects
that might affect voters with the same `user_id` and `poll_id` on
Consul Democracy installations customizing this behavior.
This commit is contained in:
Javi Martín
2024-05-11 18:49:11 +02:00
parent 9a8bfac5bd
commit b013a5b1b6
3 changed files with 78 additions and 1 deletions

View File

@@ -7,6 +7,7 @@ namespace :consul do
desc "Runs tasks needed to upgrade from 2.1.1 to 2.2.0"
task "execute_release_2.2.0_tasks": [
"db:mask_ips"
"db:mask_ips",
"polls:remove_duplicate_voters"
]
end

27
lib/tasks/polls.rake Normal file
View File

@@ -0,0 +1,27 @@
namespace :polls do
desc "Removes duplicate poll voters"
task remove_duplicate_voters: :environment do
logger = ApplicationLogger.new
logger.info "Removing duplicate voters in polls"
Tenant.run_on_each do
duplicate_ids = Poll::Voter.select(:user_id, :poll_id)
.group(:user_id, :poll_id)
.having("count(*) > 1")
.pluck(:user_id, :poll_id)
duplicate_ids.each do |user_id, poll_id|
voters = Poll::Voter.where(user_id: user_id, poll_id: poll_id)
voters.excluding(voters.first).each do |voter|
voter.delete
tenant_info = " on tenant #{Tenant.current_schema}" unless Tenant.default?
logger.info "Deleted duplicate record with ID #{voter.id} " \
"from the #{Poll::Voter.table_name} table " \
"with user_id #{user_id} " \
"and poll_id #{poll_id}" + tenant_info.to_s
end
end
end
end
end