Add task to delete duplicate poll answers

This commit is contained in:
Javi Martín
2024-05-15 16:46:05 +02:00
parent 81abbd5021
commit d2ec73e92c
4 changed files with 117 additions and 1 deletions

View File

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

View File

@@ -28,4 +28,37 @@ namespace :polls do
end end
end end
end end
desc "Removes duplicate poll answers"
task remove_duplicate_answers: :environment do
logger = ApplicationLogger.new
duplicate_records_logger = DuplicateRecordsLogger.new
logger.info "Removing duplicate answers in polls"
Tenant.run_on_each do
duplicate_ids = Poll::Answer.where(option_id: nil)
.select(:question_id, :author_id, :answer)
.group(:question_id, :author_id, :answer)
.having("count(*) > 1")
.pluck(:question_id, :author_id, :answer)
duplicate_ids.each do |question_id, author_id, answer|
poll_answers = Poll::Answer.where(question_id: question_id, author_id: author_id, answer: answer)
poll_answers.excluding(poll_answers.first).each do |poll_answer|
poll_answer.delete
tenant_info = " on tenant #{Tenant.current_schema}" unless Tenant.default?
log_message = "Deleted duplicate record with ID #{poll_answer.id} " \
"from the #{Poll::Answer.table_name} table " \
"with question_id #{question_id}, " \
"author_id #{author_id} " \
"and answer #{answer}" + tenant_info.to_s
logger.info(log_message)
duplicate_records_logger.info(log_message)
end
end
end
end
end end

View File

@@ -73,6 +73,14 @@ FactoryBot.define do
end end
end end
trait :abcde do
after(:create) do |question|
%w[A B C D E].each do |letter|
create(:poll_question_option, question: question, title: "Answer #{letter}")
end
end
end
factory :poll_question_unique do factory :poll_question_unique do
after(:create) do |question| after(:create) do |question|
create(:votation_type_unique, questionable: question) create(:votation_type_unique, questionable: question)

View File

@@ -46,4 +46,78 @@ describe "polls tasks" do
end end
end end
end end
describe "polls:remove_duplicate_answers" do
before { Rake::Task["polls:remove_duplicate_answers"].reenable }
it "removes duplicate answers" do
question = create(:poll_question_multiple, :abcde, poll: poll, max_votes: 4)
abc_question = create(:poll_question_multiple, :abc, poll: poll)
answer_attributes = {
question_id: question.id,
author_id: user.id,
answer: "Answer A",
option_id: nil
}
abc_answer_attributes = answer_attributes.merge(question_id: abc_question.id, answer: "Answer B")
answer = create(:poll_answer, answer_attributes)
other_answer = create(:poll_answer, answer_attributes.merge(answer: "Answer B"))
other_user_answer = create(:poll_answer, answer_attributes.merge(author_id: create(:user).id))
abc_answer = create(:poll_answer, abc_answer_attributes)
2.times { insert(:poll_answer, answer_attributes) }
insert(:poll_answer, abc_answer_attributes)
expect(Poll::Answer.count).to eq 7
Rake.application.invoke_task("polls:remove_duplicate_answers")
expect(Poll::Answer.count).to eq 4
expect(Poll::Answer.all).to match_array [answer, other_answer, other_user_answer, abc_answer]
end
it "does not remove answers with the same text and different options" do
question = create(:poll_question_multiple, :abcde, max_votes: 4)
option_a = question.question_options.find_by(title: "Answer A")
option_b = question.question_options.find_by(title: "Answer B")
answer_attributes = { question: question, author: user, answer: "Answer A" }
create(:poll_answer, answer_attributes.merge(option: option_a))
create(:poll_answer, answer_attributes.merge(option: option_b))
expect(Poll::Answer.count).to eq 2
Rake.application.invoke_task("polls:remove_duplicate_answers")
expect(Poll::Answer.count).to eq 2
end
it "removes duplicate answers on tenants" do
create(:tenant, schema: "answers")
Tenant.switch("answers") do
user = create(:user, :level_two)
question = create(:poll_question_multiple, :abc)
answer_attributes = {
question_id: question.id,
author_id: user.id,
answer: "Answer A",
option_id: nil
}
create(:poll_answer, answer_attributes)
insert(:poll_answer, answer_attributes)
expect(Poll::Answer.count).to eq 2
end
Rake.application.invoke_task("polls:remove_duplicate_answers")
Tenant.switch("answers") do
expect(Poll::Answer.count).to eq 1
end
end
end
end end