Add validations for changing votation type

This commit is contained in:
taitus
2025-08-06 12:13:13 +02:00
parent 9ff167d040
commit b4b00487cc
5 changed files with 66 additions and 25 deletions

View File

@@ -1,6 +1,8 @@
class VotationType < ApplicationRecord class VotationType < ApplicationRecord
belongs_to :questionable, polymorphic: true belongs_to :questionable, polymorphic: true
validate :cannot_be_open_ended_if_question_has_options
QUESTIONABLE_TYPES = %w[Poll::Question].freeze QUESTIONABLE_TYPES = %w[Poll::Question].freeze
enum :vote_type, { unique: 0, multiple: 1, open: 2 } enum :vote_type, { unique: 0, multiple: 1, open: 2 }
@@ -18,4 +20,10 @@ class VotationType < ApplicationRecord
def max_votes_required? def max_votes_required?
multiple? multiple?
end end
def cannot_be_open_ended_if_question_has_options
if questionable&.question_options&.any? && !accepts_options?
errors.add(:vote_type, :cannot_change_to_open_ended)
end
end
end end

View File

@@ -629,6 +629,10 @@ en:
attributes: attributes:
code: code:
invalid: "must start with the same code as its target followed by a dot and end with a number" invalid: "must start with the same code as its target followed by a dot and end with a number"
votation_type:
attributes:
vote_type:
cannot_change_to_open_ended: "can't change to open-ended type because you've already defined possible valid answers for this question"
messages: messages:
translations_too_short: Is mandatory to provide one translation at least translations_too_short: Is mandatory to provide one translation at least
record_invalid: "Validation failed: %{errors}" record_invalid: "Validation failed: %{errors}"

View File

@@ -629,6 +629,10 @@ es:
attributes: attributes:
code: code:
invalid: "debe empezar con el código de su meta seguido de un punto y terminar con un número" invalid: "debe empezar con el código de su meta seguido de un punto y terminar con un número"
votation_type:
attributes:
vote_type:
cannot_change_to_open_ended: "no se puede cambiar a respuesta abierta el tipo de votación porque ya has definido posibles respuestas válidas para esta pregunta"
messages: messages:
translations_too_short: El obligatorio proporcionar una traducción como mínimo translations_too_short: El obligatorio proporcionar una traducción como mínimo
record_invalid: "Error de validación: %{errors}" record_invalid: "Error de validación: %{errors}"

View File

@@ -52,6 +52,7 @@ end
section "Creating Poll Questions & Options" do section "Creating Poll Questions & Options" do
Poll.find_each do |poll| Poll.find_each do |poll|
(3..5).to_a.sample.times do (3..5).to_a.sample.times do
vote_type = VotationType.vote_types.keys.sample
question_title = Faker::Lorem.sentence(word_count: 3).truncate(60) + "?" question_title = Faker::Lorem.sentence(word_count: 3).truncate(60) + "?"
question = Poll::Question.new(author: User.sample, question = Poll::Question.new(author: User.sample,
title: question_title, title: question_title,
@@ -62,33 +63,29 @@ section "Creating Poll Questions & Options" do
end end
end end
question.save! question.save!
Faker::Lorem.words(number: (2..4).to_a.sample).each_with_index do |title, index|
description = "<p>#{Faker::Lorem.paragraphs.join("</p><p>")}</p>" question.create_votation_type!(vote_type: vote_type, max_votes: (3 if vote_type == "multiple"))
option = Poll::Question::Option.new(question: question,
title: title.capitalize, if question.accepts_options?
description: description, Faker::Lorem.words(number: (2..4).to_a.sample).each_with_index do |title, index|
given_order: index + 1) description = "<p>#{Faker::Lorem.paragraphs.join("</p><p>")}</p>"
Setting.enabled_locales.map do |locale| option = Poll::Question::Option.new(question: question,
Globalize.with_locale(locale) do title: title.capitalize,
option.title = "#{title} (#{locale})" description: description,
option.description = "#{description} (#{locale})" given_order: index + 1)
Setting.enabled_locales.map do |locale|
Globalize.with_locale(locale) do
option.title = "#{title} (#{locale})"
option.description = "#{description} (#{locale})"
end
end end
option.save!
end end
option.save!
end end
end end
end end
end end
section "Creating Poll Votation types" do
poll = Poll.first
poll.questions.each do |question|
vote_type = VotationType.vote_types.keys.sample
question.create_votation_type!(vote_type: vote_type, max_votes: (3 unless vote_type == "unique"))
end
end
section "Creating Poll Booths & BoothAssignments" do section "Creating Poll Booths & BoothAssignments" do
20.times do |i| 20.times do |i|
Poll::Booth.create(name: "Booth #{i}", Poll::Booth.create(name: "Booth #{i}",
@@ -158,11 +155,16 @@ section "Creating Poll Voters" do
poll.questions.each do |question| poll.questions.each do |question|
next unless [true, false].sample next unless [true, false].sample
option = question.question_options.sample if question.accepts_options?
Poll::Answer.create!(question_id: question.id, option = question.question_options.sample
author: user, Poll::Answer.create!(question_id: question.id,
option: option, author: user,
answer: option.title) option: option,
answer: option.title)
else
text = Faker::Lorem.sentence(word_count: (6..14).to_a.sample)
Poll::Answer.create!(question_id: question.id, author: user, answer: text)
end
end end
end end
@@ -254,6 +256,7 @@ section "Creating Poll Questions from Proposals" do
end end
option.save! option.save!
end end
question.create_votation_type!(vote_type: "unique")
end end
end end

View File

@@ -36,4 +36,26 @@ describe VotationType do
expect(votation_type).not_to be_valid expect(votation_type).not_to be_valid
expect(votation_type.errors[:max_votes]).to include "can't be blank" expect(votation_type.errors[:max_votes]).to include "can't be blank"
end end
describe "#cannot_be_open_ended_if_question_has_options" do
it "allows changing to open-ended when the question has no options" do
votation_type = create(:votation_type_unique)
votation_type.vote_type = :open
expect(votation_type).to be_valid
end
it "blocks changing to open-ended when the question has options" do
votation_type = create(:votation_type_unique)
create(:poll_question_option, question: votation_type.questionable)
votation_type.vote_type = :open
expect(votation_type).not_to be_valid
error = votation_type.errors[:vote_type].first
expect(error).to eq "can't change to open-ended type " \
"because you've already defined possible valid answers for this question"
end
end
end end