Just a short intro. Back in Rail 5.x error I threw together a Bingo caller app. I was a volunteer at a VFW Post(Quartermaster) and we were exploring of having a Bingo game at the Post. After looking at the cost of some stuff (the big Bingo call board), I wrote the app.
It was pretty simple. Just a game model that serialized the calls. This was all in coffeescript, jquery etc. It had a caller view that would add the calls to the game by clicking on a button for each of the 60 numbers.
I had a viewer view the just displayed the board. I ran the viewer on a RasberryPI hooked to a large screen TV. It would refersh about every 5 seconds. Fortunatly we decided not to add the Bingo night.
I didn’t have anything to do and threw togother a new app to recreate Bingo in Rails 7. The code was much smaller using TW, Stimulus etc. Problem was I was still using JS to refresh the page, why not used Turbo frames and broadcast!
The frames where not hard but I’m stuck on getting broadcast to work. The Game model has three methods (beside CRUD methods)
def play
@game = Game.current
end
def call
@game.set_call(params[:numb])
if @game.changed?
@game.save
@game.broadcast_replace_later_to "watcher", partial: "games/watcher", locals: { game: @game }
end
render turbo_stream: turbo_stream.replace(
'call',
partial: '/games/call')
end
def watcher
@game = Game.current
end
The views are also simple, I use slim. I also use a helper to add classes to the buttons depending on what column the number is in.
# games/play The callers control panel
div.bg-black.flex.gap-8
div.text-white.m-2 Btn1
div.text-white.m-2 Btn2
div.text-white.m-2 Btnx
== render partial:"games/call"
# games/_call
=turbo_frame_tag "call"
div.bg-black
- colors = ["B","I","N","G","O"]
- 0.upto(4) do |row|
div.flex
- box = "btnOff" + colors[row]
div[class=send(box)] = colors[row]
- 1.upto(15) do |col|
- numb = row * 15 + col
- if @game.calls.include?(numb)
- klass = "btnOn"+ colors[row]
= button_to(numb,call_game_path(@game),method:"patch",form_class:send(klass),params:{numb:numb})
- else
- klass = "btnOff"+ colors[row]
= button_to(numb,call_game_path(@game),method:"patch",form_class:send(klass),params:{numb:numb})
div.text-white.m-2 Call Stack First -> Last (left to right)
div.flex.flex-wrap
- @game.calls.each do |c|
- btn = "btnOn" + call_color(c)
div[class=send(btn)] = c
div.text-white.p-8 more stuff
# games/watcher
div
== render partial:'games/watcher', locals:{game:@game}
# games/_watcher
= turbo_frame_tag "watcher"
div.bg-black.flex.gap-8
div.text-white.m-2 = link_to("Exit",home_path,data:{action:"refresh#stopRefresh"})
div[data-refresh-target="updated" class="text-white m-2"] = game.updated_at.to_s
# the rest is same a call, except the buttons are just div's not actions.
So all is working except for
@game.broadcast_replace_later_to "watcher", partial: "games/watcher", locals: { game: @game }
I’ve tried both broadcast_replace_to
and broadcast_replace_later_to
. neither change the watcher view and produce the following log after the call is saved:
#with later broadcast_replace_later_to
14:35:10 web.1 | [ActiveJob] [Turbo::Streams::ActionBroadcastJob] [e73ed3ee-a387-4a57-9f7d-f93c28d6c946] Game Load (0.1ms) SELECT "games".* FROM "games" WHERE "games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
14:35:10 web.1 | [ActiveJob] [Turbo::Streams::ActionBroadcastJob] [e73ed3ee-a387-4a57-9f7d-f93c28d6c946] CACHE Game Load (0.0ms) SELECT "games".* FROM "games" WHERE "games"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
14:35:10 web.1 | [ActiveJob] [Turbo::Streams::ActionBroadcastJob] [e73ed3ee-a387-4a57-9f7d-f93c28d6c946] Performing Turbo::Streams::ActionBroadcastJob (Job ID: e73ed3ee-a387-4a57-9f7d-f93c28d6c946) from Async(default) enqueued at 2022-10-26T19:35:10Z with arguments: "watcher", {:action=>:replace, :target=>#<GlobalID:0x000000011225c840 @uri=#<URI::GID gid://bingo/Game/1>>, :targets=>nil, :partial=>"games/watcher", :locals=>{:game=>#<GlobalID:0x000000011225c278 @uri=#<URI::GID gid://bingo/Game/1>>}}
14:35:10 web.1 | [ActiveJob] [Turbo::Streams::ActionBroadcastJob] [e73ed3ee-a387-4a57-9f7d-f93c28d6c946] Rendered games/_watcher.html.slim (Duration: 4.9ms | Allocations: 10099)
14:35:10 web.1 | [ActiveJob] [Turbo::Streams::ActionBroadcastJob] [e73ed3ee-a387-4a57-9f7d-f93c28d6c946] [ActionCable] Broadcasting to watcher: "<turbo-stream action=\"replace\" target=\"game_1\"><template><turbo-frame id=\"watcher\"><div class=\"bg-black flex gap-8\"><div class=\"text-white m-2\"><a data-action=\"refresh#stopRefresh\" href=\"/home\">Exit</a></div><div class=\"text-white m-2\" data-refresh-target=\"updated\">2022-10-26 1...
14:35:11 web.1 | [ActiveJob] [Turbo::Streams::ActionBroadcastJob] [e73ed3ee-a387-4a57-9f7d-f93c28d6c946] Performed Turbo::Streams::ActionBroadcastJob (Job ID: e73ed3ee-a387-4a57-9f7d-f93c28d6c946) from Async(default) in 8.89ms
# ascync broadcast_replace_to
14:41:03 web.1 | Rendered games/_watcher.html.slim (Duration: 1.3ms | Allocations: 1468)
14:41:03 web.1 | [ActionCable] Broadcasting to watcher: "<turbo-stream action=\"replace\" target=\"game_1\"><template><turbo-frame id=\"watcher\"><div class=\"bg-black flex gap-8\"><div class=\"text-white m-2\"><a data-action=\"refresh#stopRefresh\" href=\"/home\">Exit</a></div><div class=\"text-white m-2\" data-refresh-target=\"updated\">2022-10-26 1...
14:41:03 web.1 | Rendered games/_call.html.slim (Duration: 13.5ms | Allocations: 21910)
14:41:03 web.1 | Completed 200 OK in 30ms (Views: 0.1ms | ActiveRecord: 1.5ms | Allocations: 30007)
14:41:03 web.1 |
So it’s beyond my knowledge. I was wondering broadcast_to was not documented in Rails - Because it’s in Turbo with little expaination on how it work,
I’m just stumped. I am on OSX if that makes a difference.