Add questions with mutiple answers to polls public interface
The `reload` method added to max_votes validation is needed because the author gets here with some changes because of the around_action `switch_locale`, which adds some changes to the current user record and therefore, the lock method raises an exception when trying to lock it requiring us to save or discard those record changes.
This commit is contained in:
committed by
Senén Rodero Rodríguez
parent
3da4112d94
commit
36e452437e
@@ -15,7 +15,8 @@
|
|||||||
remote: true,
|
remote: true,
|
||||||
title: t("poll_questions.show.vote_answer", answer: question_answer.title),
|
title: t("poll_questions.show.vote_answer", answer: question_answer.title),
|
||||||
class: "button secondary hollow",
|
class: "button secondary hollow",
|
||||||
"aria-pressed": false do %>
|
"aria-pressed": false,
|
||||||
|
disabled: disable_answer?(question_answer) do %>
|
||||||
<%= question_answer.title %>
|
<%= question_answer.title %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ class Polls::Questions::AnswersComponent < ApplicationComponent
|
|||||||
user_answers.find_by(answer: question_answer.title)
|
user_answers.find_by(answer: question_answer.title)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def disable_answer?(question_answer)
|
||||||
|
question.multiple? && user_answers.count == question.max_votes
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def user_answers
|
def user_answers
|
||||||
|
|||||||
@@ -3,6 +3,12 @@
|
|||||||
<%= question.title %>
|
<%= question.title %>
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
|
<% if question.votation_type.present? %>
|
||||||
|
<strong>
|
||||||
|
<%= t("poll_questions.description.#{question.vote_type}", maximum: question.max_votes) %>
|
||||||
|
</strong>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
<div id="<%= dom_id(question) %>_answers" class="padding">
|
<div id="<%= dom_id(question) %>_answers" class="padding">
|
||||||
<%= render Polls::Questions::AnswersComponent.new(question) %>
|
<%= render Polls::Questions::AnswersComponent.new(question) %>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,9 +5,7 @@ class Polls::QuestionsController < ApplicationController
|
|||||||
has_orders %w[most_voted newest oldest], only: :show
|
has_orders %w[most_voted newest oldest], only: :show
|
||||||
|
|
||||||
def answer
|
def answer
|
||||||
answer = @question.answers.find_or_initialize_by(author: current_user)
|
answer = @question.find_or_initialize_user_answer(current_user, params[:answer])
|
||||||
|
|
||||||
answer.answer = params[:answer]
|
|
||||||
answer.save_and_record_voter_participation
|
answer.save_and_record_voter_participation
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
@@ -15,7 +13,7 @@ class Polls::QuestionsController < ApplicationController
|
|||||||
redirect_to request.referer
|
redirect_to request.referer
|
||||||
end
|
end
|
||||||
format.js do
|
format.js do
|
||||||
render :answer
|
render :answers
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -10,4 +10,21 @@ module Questionable
|
|||||||
def unique?
|
def unique?
|
||||||
votation_type.nil? || votation_type.unique?
|
votation_type.nil? || votation_type.unique?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def find_or_initialize_user_answer(user, title)
|
||||||
|
answer = answers.find_or_initialize_by(find_by_attributes(user, title))
|
||||||
|
answer.answer = title
|
||||||
|
answer
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def find_by_attributes(user, title)
|
||||||
|
case vote_type
|
||||||
|
when "unique", nil
|
||||||
|
{ author: user }
|
||||||
|
when "multiple"
|
||||||
|
{ author: user, answer: title }
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ class Poll::Answer < ApplicationRecord
|
|||||||
def max_votes
|
def max_votes
|
||||||
return if !question || question&.unique? || persisted?
|
return if !question || question&.unique? || persisted?
|
||||||
|
|
||||||
|
author.reload
|
||||||
author.lock!
|
author.lock!
|
||||||
|
|
||||||
if question.answers.by_author(author).count >= question.max_votes
|
if question.answers.by_author(author).count >= question.max_votes
|
||||||
|
|||||||
@@ -636,6 +636,9 @@ en:
|
|||||||
show:
|
show:
|
||||||
vote_answer: "Vote %{answer}"
|
vote_answer: "Vote %{answer}"
|
||||||
voted: "You have voted %{answer}"
|
voted: "You have voted %{answer}"
|
||||||
|
description:
|
||||||
|
unique: "You can select a maximum of 1 answer."
|
||||||
|
multiple: "You can select a maximum of %{maximum} answers."
|
||||||
proposal_notifications:
|
proposal_notifications:
|
||||||
new:
|
new:
|
||||||
title: "Send notification"
|
title: "Send notification"
|
||||||
|
|||||||
@@ -636,6 +636,9 @@ es:
|
|||||||
show:
|
show:
|
||||||
vote_answer: "Votar %{answer}"
|
vote_answer: "Votar %{answer}"
|
||||||
voted: "Has votado %{answer}"
|
voted: "Has votado %{answer}"
|
||||||
|
description:
|
||||||
|
unique: "Puedes seleccionar un máximo de 1 respuesta."
|
||||||
|
multiple: "Puedes seleccionar un máximo de %{maximum} respuestas."
|
||||||
proposal_notifications:
|
proposal_notifications:
|
||||||
new:
|
new:
|
||||||
title: "Enviar notificación"
|
title: "Enviar notificación"
|
||||||
|
|||||||
@@ -33,6 +33,20 @@ describe Polls::Questions::AnswersComponent do
|
|||||||
expect(page).to have_css "button[aria-pressed='true']", text: "Yes"
|
expect(page).to have_css "button[aria-pressed='true']", text: "Yes"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "renders disabled buttons when max votes is reached" do
|
||||||
|
user = create(:user, :verified)
|
||||||
|
question = create(:poll_question_multiple, :abc, max_votes: 2, author: user)
|
||||||
|
create(:poll_answer, author: user, question: question, answer: "Answer A")
|
||||||
|
create(:poll_answer, author: user, question: question, answer: "Answer C")
|
||||||
|
sign_in(user)
|
||||||
|
|
||||||
|
render_inline Polls::Questions::AnswersComponent.new(question)
|
||||||
|
|
||||||
|
expect(page).to have_button "You have voted Answer A"
|
||||||
|
expect(page).to have_button "Vote Answer B", disabled: true
|
||||||
|
expect(page).to have_button "You have voted Answer C"
|
||||||
|
end
|
||||||
|
|
||||||
it "when user is not signed in, renders answers links pointing to user sign in path" do
|
it "when user is not signed in, renders answers links pointing to user sign in path" do
|
||||||
render_inline Polls::Questions::AnswersComponent.new(question)
|
render_inline Polls::Questions::AnswersComponent.new(question)
|
||||||
|
|
||||||
|
|||||||
69
spec/system/polls/votation_types_spec.rb
Normal file
69
spec/system/polls/votation_types_spec.rb
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
require "rails_helper"
|
||||||
|
|
||||||
|
describe "Poll Votation Type" do
|
||||||
|
let(:author) { create(:user, :level_two) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
login_as(author)
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "Unique answer" do
|
||||||
|
question = create(:poll_question_unique, :yes_no)
|
||||||
|
|
||||||
|
visit poll_path(question.poll)
|
||||||
|
|
||||||
|
expect(page).to have_content "You can select a maximum of 1 answer."
|
||||||
|
expect(page).to have_content(question.title)
|
||||||
|
expect(page).to have_button("Vote Yes")
|
||||||
|
expect(page).to have_button("Vote No")
|
||||||
|
|
||||||
|
within "#poll_question_#{question.id}_answers" do
|
||||||
|
click_button "Yes"
|
||||||
|
|
||||||
|
expect(page).to have_button("You have voted Yes")
|
||||||
|
expect(page).to have_button("Vote No")
|
||||||
|
|
||||||
|
click_button "No"
|
||||||
|
|
||||||
|
expect(page).to have_button("Vote Yes")
|
||||||
|
expect(page).to have_button("You have voted No")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "Multiple answers" do
|
||||||
|
question = create(:poll_question_multiple, :abc, max_votes: 2)
|
||||||
|
visit poll_path(question.poll)
|
||||||
|
|
||||||
|
expect(page).to have_content "You can select a maximum of 2 answers."
|
||||||
|
expect(page).to have_content(question.title)
|
||||||
|
expect(page).to have_button("Vote Answer A")
|
||||||
|
expect(page).to have_button("Vote Answer B")
|
||||||
|
expect(page).to have_button("Vote Answer C")
|
||||||
|
|
||||||
|
within "#poll_question_#{question.id}_answers" do
|
||||||
|
click_button "Vote Answer A"
|
||||||
|
|
||||||
|
expect(page).to have_button("You have voted Answer A")
|
||||||
|
|
||||||
|
click_button "Vote Answer C"
|
||||||
|
|
||||||
|
expect(page).to have_button("You have voted Answer C")
|
||||||
|
expect(page).to have_button("Vote Answer B", disabled: true)
|
||||||
|
|
||||||
|
click_button "You have voted Answer A"
|
||||||
|
|
||||||
|
expect(page).to have_button("Vote Answer A")
|
||||||
|
expect(page).to have_button("Vote Answer B")
|
||||||
|
|
||||||
|
click_button "You have voted Answer C"
|
||||||
|
|
||||||
|
expect(page).to have_button("Vote Answer C")
|
||||||
|
|
||||||
|
click_button "Vote Answer B"
|
||||||
|
|
||||||
|
expect(page).to have_button("You have voted Answer B")
|
||||||
|
expect(page).to have_button("Vote Answer A")
|
||||||
|
expect(page).to have_button("Vote Answer C")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user