Do not allow to create more answers than the maximum defined
In case we receive consecutive requests we are locking the poll author record until the first request transaction ends, so the author answers count during subsequent requests validations is up to date.
This commit is contained in:
committed by
Senén Rodero Rodríguez
parent
a25629951c
commit
48d7ec75d0
@@ -7,6 +7,7 @@ class Poll::Answer < ApplicationRecord
|
||||
validates :question, presence: true
|
||||
validates :author, presence: true
|
||||
validates :answer, presence: true
|
||||
validate :max_votes
|
||||
|
||||
validates :answer, inclusion: { in: ->(a) { a.question.possible_answers }},
|
||||
unless: ->(a) { a.question.blank? }
|
||||
@@ -21,4 +22,16 @@ class Poll::Answer < ApplicationRecord
|
||||
Poll::Voter.find_or_create_by!(user: author, poll: poll, origin: "web")
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def max_votes
|
||||
return if !question || question&.unique? || persisted?
|
||||
|
||||
author.lock!
|
||||
|
||||
if question.answers.by_author(author).count >= question.max_votes
|
||||
errors.add(:answer, "Maximum number of votes per user exceeded")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -23,6 +23,30 @@ describe Poll::Answer do
|
||||
expect(answer).not_to be_valid
|
||||
end
|
||||
|
||||
it "is not valid when user already reached multiple answers question max votes" do
|
||||
author = create(:user)
|
||||
question = create(:poll_question_multiple, :abc, max_votes: 2)
|
||||
create(:poll_answer, author: author, question: question, answer: "Answer A")
|
||||
create(:poll_answer, author: author, question: question, answer: "Answer B")
|
||||
answer = build(:poll_answer, author: author, question: question, answer: "Answer C")
|
||||
|
||||
expect(answer).not_to be_valid
|
||||
end
|
||||
|
||||
it "validates max votes when creating answers at the same time", :race_condition do
|
||||
author = create(:user, :level_two)
|
||||
question = create(:poll_question_multiple, :abc, max_votes: 2)
|
||||
create(:poll_answer, question: question, answer: "Answer A", author: author)
|
||||
answer = build(:poll_answer, question: question, answer: "Answer B", author: author)
|
||||
other_answer = build(:poll_answer, question: question, answer: "Answer C", author: author)
|
||||
|
||||
[answer, other_answer].map do |a|
|
||||
Thread.new { a.save }
|
||||
end.each(&:join)
|
||||
|
||||
expect(Poll::Answer.count).to be 2
|
||||
end
|
||||
|
||||
it "is valid for answers included in the Poll::Question's question_answers list" do
|
||||
question = create(:poll_question)
|
||||
create(:poll_question_answer, title: "One", question: question)
|
||||
|
||||
Reference in New Issue
Block a user