Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

In which I reinstate turbo_stream#replace for polls #307

Merged
merged 1 commit into from
Dec 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions app/controllers/share/polls/votes_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,16 @@ def create
@vote = @question.votes.find_by(device_uuid: ensure_device_uuid)
@vote ||= record_vote(@answer)

@question.broadcast_replace_later \
target: [@question, :results],
html: Share::Polls::Results.new(@poll, @question).call(view_context:),
attributes: {method: :morph}

if @vote.valid?
respond_to do |format|
format.html { redirect_to [:share, @poll] }
format.html { redirect_to [:share, @poll], notice: "Thank you for voting!".emojoy }
format.turbo_stream do
flash.now[:notice] = "Thank you for voting!"
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))
Expand Down
2 changes: 0 additions & 2 deletions app/models/polls/question.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ class Polls::Question < ApplicationRecord

scope :ordered, -> { order(position: :asc, id: :asc) }

broadcasts_refreshes

def votes_count
answers.sum(&:votes_count)
end
Expand Down
31 changes: 31 additions & 0 deletions app/views/share/polls/ballot.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
module Share
module Polls
class Ballot < ApplicationComponent
include Phlex::Rails::Helpers::ButtonTo
include Phlex::Rails::Helpers::DOMID
include Phlex::Rails::Helpers::Pluralize

attr_reader :poll, :question

def initialize(poll, question, voted: false)
@poll = poll
@question = question
@voted = voted
end

def view_template
div id: dom_id(question, :ballot), class: "question flex flex-col gap-2" do
p { question.body }

question.answers.ordered.each do |answer|
div id: dom_id(answer) do
button_to answer.body,
share_poll_votes_path(poll, answer_id: answer.id),
class: "button transparent slim"
end
end
end
end
end
end
end
12 changes: 2 additions & 10 deletions app/views/share/polls/lazy_page_poll.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module Share
module Polls
class LazyPagePoll < ApplicationComponent
include Phlex::Rails::Helpers::Provide
include Phlex::Rails::Helpers::Request
include Phlex::Rails::Helpers::TurboFrameTag
include Phlex::Rails::Helpers::TurboRefreshesWith

attr_reader :page, :title, :question_data
Expand All @@ -14,15 +14,7 @@ def initialize(page, title, question_data = {})

def view_template
poll = Poll.generate_for(page, title, question_data) or return

provide :head, turbo_refreshes_with(method: :morph, scroll: :preserve)
render Share::Polls::PollComponent.new(poll, device_uuid: device_uuid)
end

def device_uuid
return "" unless helpers.request.key_generator

helpers.cookies.signed[:device_uuid]
turbo_frame_tag poll, src: share_poll_path(poll), class: "poll"
end
end
end
Expand Down
6 changes: 3 additions & 3 deletions app/views/share/polls/poll_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ def view_template
.includes(:answers)
.ordered
.each do |question|
render Share::Polls::Question.new(
poll:,
question:,
render Share::Polls::QuestionComponent.new(
poll,
question,
voted: question.voted?(device_uuid: device_uuid)
)
end
Expand Down
31 changes: 31 additions & 0 deletions app/views/share/polls/question_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
module Share
module Polls
class QuestionComponent < ApplicationComponent
include Phlex::Rails::Helpers::TurboFrameTag
include Phlex::Rails::Helpers::TurboStreamFrom

attr_reader :poll, :question

def initialize(poll, question, voted: false)
@poll = poll
@question = question
@voted = voted
end

def view_template
turbo_frame_tag question, class: "question flex flex-col gap-2" do
if voted?
render Share::Polls::Results.new(poll, question)
else
render Share::Polls::Ballot.new(poll, question)
end
end
turbo_stream_from question
end

private

def voted? = !!@voted
end
end
end
Original file line number Diff line number Diff line change
@@ -1,59 +1,32 @@
module Share
module Polls
class Question < ApplicationComponent
include Phlex::Rails::Helpers::ButtonTo
include Phlex::Rails::Helpers::DOMID
class Results < ApplicationComponent
include Phlex::Rails::Helpers::Pluralize
include Phlex::Rails::Helpers::TurboFrameTag
include Phlex::Rails::Helpers::TurboStreamFrom
include Phlex::Rails::Helpers::DOMID

attr_reader :poll, :question

def initialize(poll:, question:, voted: false)
def initialize(poll, question)
@poll = poll
@question = question
@voted = voted
end

def view_template
turbo_frame_tag question, class: "question flex flex-col gap-2" do
if voted?
results
else
ballot
end
end
turbo_stream_from question
end

def ballot
p { question.body }
div id: dom_id(question, :results), class: "question flex flex-col gap-2" do
p { question.body }

question.answers.ordered.each do |answer|
div id: dom_id(answer) do
button_to answer.body,
share_poll_votes_path(poll, answer_id: answer.id),
class: "button transparent slim"
question.answers.ordered.each do |answer|
render AnswerBar.new(answer, question)
end
end
end

def results
p { question.body }

question.answers.ordered.each do |answer|
render AnswerBar.new(answer, question)
end

div(class: "p-2") do
p(class: "text-small font-extrabold") { pluralize question.votes_count, "vote" }
div(class: "p-2") do
p(class: "text-small font-extrabold") { pluralize question.votes_count, "vote" }
end
end
end

private

def voted? = !!@voted

class AnswerBar < ApplicationComponent
include Phlex::Rails::Helpers::DOMID
include Phlex::Rails::Helpers::NumberToPercentage
Expand Down
15 changes: 10 additions & 5 deletions spec/system/share/polls_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,15 @@
expect(page).to have_content("2 votes")
end

# We could theoretically test that the original user sees the refreshed
# results but I could only get this to work in system tests when the
# broadcast was emitted in process while "refresh later" via background job,
# as I would prefer it work, doesn’t seem to work with test adapters for
# solid cable / solid queue.
# Assert the vote results are broadcasted to the other guest session
perform_enqueued_jobs

within("#polls_answer_#{answer1.id}") do
expect(page).to have_content("50.0")
end
within("#polls_answer_#{answer2.id}") do
expect(page).to have_content("50.0%")
end
expect(page).to have_content("2 votes")
end
end
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
require "rails_helper"

RSpec.describe Share::Polls::Question, type: :view do
RSpec.describe Share::Polls::QuestionComponent, type: :view do
context "when not voted on" do
it "renders with no answers" do
poll = FactoryBot.create(:poll)
question = FactoryBot.create(:polls_question, poll:)

render described_class.new(poll:, question:, voted: false)
render described_class.new(poll, question, voted: false)

expect(rendered).to have_css("p")
end
Expand All @@ -16,7 +16,7 @@
question = FactoryBot.create(:polls_question, poll:)
FactoryBot.create(:polls_answer, question:)

render described_class.new(poll:, question:, voted: false)
render described_class.new(poll, question, voted: false)

expect(rendered).to have_css("button", count: 1)
end
Expand All @@ -27,7 +27,7 @@
FactoryBot.create(:polls_answer, question:)
FactoryBot.create(:polls_answer, question:)

render described_class.new(poll:, question:, voted: false)
render described_class.new(poll, question, voted: false)

expect(rendered).to have_css("button", count: 2)
end
Expand All @@ -39,7 +39,7 @@
question = FactoryBot.create(:polls_question, poll:)
FactoryBot.create(:polls_answer, question:)

render described_class.new(poll:, question:, voted: true)
render described_class.new(poll, question, voted: true)

expect(rendered).to have_css(".question")
expect(rendered).to have_css(".answer")
Expand All @@ -53,7 +53,7 @@
answer = FactoryBot.create(:polls_answer, question:)
FactoryBot.create(:polls_vote, answer:)

render described_class.new(poll:, question:, voted: true)
render described_class.new(poll, question, voted: true)

expect(rendered).to have_css(".question")
expect(rendered).to have_css(".answer")
Expand Down
Loading