Don't save the answer if the voter is not recorded

Up until now, we were assuming the voter was valid, but were not raising
an exception if it wasn't. And in the user interface everything seemed
to be working properly.

We were having this issue when skipping verification, when there could
be voters without a document number, which would be considered invalid.

Raising an exception when failing to save the voter and making sure the
answer and the voter are saved inside a transaction solves the problem.
This commit is contained in:
Javi Martín
2020-08-06 21:44:09 +02:00
parent 50372f4370
commit 24ccf23ed8
3 changed files with 22 additions and 9 deletions

View File

@@ -9,9 +9,7 @@ class Polls::QuestionsController < ApplicationController
token = params[:token]
answer.answer = params[:answer]
answer.touch if answer.persisted?
answer.save!
answer.record_voter_participation(token)
answer.save_and_record_voter_participation(token)
@answers_by_question_id = { @question.id => params[:answer] }
end

View File

@@ -14,7 +14,11 @@ class Poll::Answer < ApplicationRecord
scope :by_author, ->(author_id) { where(author_id: author_id) }
scope :by_question, ->(question_id) { where(question_id: question_id) }
def record_voter_participation(token)
Poll::Voter.find_or_create_by(user: author, poll: poll, origin: "web", token: token)
def save_and_record_voter_participation(token)
transaction do
touch if persisted?
save!
Poll::Voter.find_or_create_by!(user: author, poll: poll, origin: "web", token: token)
end
end
end

View File

@@ -37,7 +37,7 @@ describe Poll::Answer do
end
end
describe "#record_voter_participation" do
describe "#save_and_record_voter_participation" do
let(:author) { create(:user, :level_two) }
let(:poll) { create(:poll) }
let(:question) { create(:poll_question, :yes_no, poll: poll) }
@@ -46,7 +46,7 @@ describe Poll::Answer do
answer = create(:poll_answer, question: question, author: author, answer: "Yes")
expect(answer.poll.voters).to be_blank
answer.record_voter_participation("token")
answer.save_and_record_voter_participation("token")
expect(poll.reload.voters.size).to eq(1)
voter = poll.voters.first
@@ -57,12 +57,12 @@ describe Poll::Answer do
it "updates a poll_voter with user and poll data" do
answer = create(:poll_answer, question: question, author: author, answer: "Yes")
answer.record_voter_participation("token")
answer.save_and_record_voter_participation("token")
expect(poll.reload.voters.size).to eq(1)
answer = create(:poll_answer, question: question, author: author, answer: "No")
answer.record_voter_participation("token")
answer.save_and_record_voter_participation("token")
expect(poll.reload.voters.size).to eq(1)
@@ -70,5 +70,16 @@ describe Poll::Answer do
expect(voter.document_number).to eq(answer.author.document_number)
expect(voter.poll_id).to eq(answer.poll.id)
end
it "does not save the answer if the voter is invalid" do
allow_any_instance_of(Poll::Voter).to receive(:valid?).and_return(false)
answer = build(:poll_answer)
expect do
answer.save_and_record_voter_participation("token")
end.to raise_error(ActiveRecord::RecordInvalid)
expect(answer).not_to be_persisted
end
end
end