Skip to content

Commit

Permalink
Merge pull request #331 from joyofrails/feat/voted-query
Browse files Browse the repository at this point in the history
Fix for vote query
  • Loading branch information
rossta authored Dec 23, 2024
2 parents 7edc44f + 03dbf18 commit fcfa8c9
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 14 deletions.
5 changes: 4 additions & 1 deletion app/controllers/share/polls/votes_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ def create
flash.now[:notice] = "Thank you for voting!".emojoy
render turbo_stream: [
turbo_stream.prepend("flash", partial: "application/flash"),
turbo_stream.replace(@poll, renderable: Share::Polls::PollComponent.new(@poll, device_uuid: ensure_device_uuid))
turbo_stream.replace(
@poll,
renderable: Share::Polls::PollComponent.new(@poll, completed: @poll.voted_all?(device_uuid: ensure_device_uuid))
)
]
end
end
Expand Down
14 changes: 14 additions & 0 deletions app/models/poll.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,18 @@ def self.generate_for(
poll.save
poll
end

def voted_all?(vote_conditions)
counts = questions
.select(:id)
.left_joins(:votes)
.where(votes: vote_conditions)
.group(:id)
.count # {question_id => votes_count}

# Check if all questions have at least one vote We might expect counts to
# include zeros for questions without votes but the left join appears to
# exclude them, so we fetch(id, 0) to default to 0.
question_ids.all? { |id| counts.fetch(id, 0).positive? }
end
end
4 changes: 0 additions & 4 deletions app/models/polls/question.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,4 @@ class Polls::Question < ApplicationRecord
def votes_count
answers.sum(&:votes_count)
end

def voted?(**conditions)
votes.where(**conditions).count.positive?
end
end
2 changes: 1 addition & 1 deletion app/views/share/polls/_poll.html.erb
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<%= render Share::Polls::PollComponent.new(poll, device_uuid: ensure_device_uuid) %>
<%= render Share::Polls::PollComponent.new(poll, completed: poll.voted_all?(device_uuid: ensure_device_uuid)) %>
19 changes: 11 additions & 8 deletions app/views/share/polls/poll_component.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
class Share::Polls::PollComponent < ApplicationComponent
include Phlex::Rails::Helpers::TurboFrameTag

attr_accessor :poll, :device_uuid
attr_accessor :poll

def initialize(poll, device_uuid:)
def initialize(poll, completed: false)
@poll = poll
@device_uuid = device_uuid
@completed = completed
end

def view_template
Expand All @@ -17,18 +17,21 @@ def view_template
end

div(class: "p-4 flex flex-col gap-2") do
poll
.questions
.includes(:answers)
.ordered
questions
.each do |question|
render Share::Polls::QuestionComponent.new(
poll,
question,
voted: question.voted?(device_uuid: device_uuid)
voted: completed?
)
end
end
end
end

def questions
@questions ||= poll.questions.includes(:answers).ordered
end

def completed? = !!@completed
end
25 changes: 25 additions & 0 deletions spec/models/poll_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,29 @@
}.not_to change(Poll, :count)
end
end

describe "#voted_all?" do
it "returns true if all questions have been voted on" do
poll = FactoryBot.create(:poll)
q1 = FactoryBot.create(:polls_question, poll: poll)
q2 = FactoryBot.create(:polls_question, poll: poll)
q3 = FactoryBot.create(:polls_question, poll: poll)
a1_q1 = FactoryBot.create(:polls_answer, question: q1)
_a2_q1 = FactoryBot.create(:polls_answer, question: q1)
_a1_q2 = FactoryBot.create(:polls_answer, question: q2)
a2_q2 = FactoryBot.create(:polls_answer, question: q2)
_a1_q3 = FactoryBot.create(:polls_answer, question: q3)
a2_q3 = FactoryBot.create(:polls_answer, question: q3)

uuid = SecureRandom.uuid_v7
FactoryBot.create(:polls_vote, answer: a1_q1, device_uuid: uuid)
FactoryBot.create(:polls_vote, answer: a2_q2, device_uuid: uuid)

expect(poll.voted_all?(device_uuid: uuid)).to eq(false)

FactoryBot.create(:polls_vote, answer: a2_q3, device_uuid: uuid)

expect(poll.voted_all?(device_uuid: uuid)).to eq(true)
end
end
end

0 comments on commit fcfa8c9

Please sign in to comment.