From c657a390351748075874e73d75a7408245e00682 Mon Sep 17 00:00:00 2001 From: Dirk Jonker Date: Fri, 7 Jul 2023 11:38:16 +0200 Subject: [PATCH] Convert DOM IDs before submitting ActionBroadcastJob When broadcasting to a target with a suffix, i.e. ```ruby target: [active_record_instance, :some_attribute] ``` The array will get passed to `ActionView::RecordIdentifier.dom_id` which turn it into something like: `"active_record_instance_1234_some_attribute"`. This works fine when broadcasting synchronously, but because array gets serialized into a parameter for the `ActionBroadcastJob`, it ends up forming an illegal target, something like: `"# some_attribute"` This seems to include a memory address so it should be pretty much guaranteed that it does not result in any predictable changes to the DOM. This behavior difference is a bit confusing and hard to debug. This change generates the `target` names before serializing the job parameters, to keep the behavior consistent between the regulater and `later` methods. Behavior for existing applications may or may not change, depending on whether people expect this not to work. --- app/channels/turbo/streams/broadcasts.rb | 2 ++ test/streams/streams_channel_test.rb | 29 ++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/app/channels/turbo/streams/broadcasts.rb b/app/channels/turbo/streams/broadcasts.rb index f3aabd39..3a975d5c 100644 --- a/app/channels/turbo/streams/broadcasts.rb +++ b/app/channels/turbo/streams/broadcasts.rb @@ -64,6 +64,8 @@ def broadcast_prepend_later_to(*streamables, **opts) end def broadcast_action_later_to(*streamables, action:, target: nil, targets: nil, **rendering) + target = convert_to_turbo_stream_dom_id(target) + targets = convert_to_turbo_stream_dom_id(targets, include_selector: true) Turbo::Streams::ActionBroadcastJob.perform_later \ stream_name_from(streamables), action: action, target: target, targets: targets, **rendering end diff --git a/test/streams/streams_channel_test.rb b/test/streams/streams_channel_test.rb index dea35c6f..5d473453 100644 --- a/test/streams/streams_channel_test.rb +++ b/test/streams/streams_channel_test.rb @@ -190,6 +190,35 @@ class Turbo::StreamsChannelTest < ActionCable::Channel::TestCase end end + test "broadcasting action later with ActiveModel array target" do + options = { partial: "messages/message", locals: { message: "hello!" } } + + message = Message.new(id: 42) + target = [message, "opt"] + expected_target = "opt_message_42" + + assert_broadcast_on "stream", turbo_stream_action_tag("prepend", target: expected_target, template: render(options)) do + perform_enqueued_jobs do + Turbo::StreamsChannel.broadcast_action_later_to \ + "stream", action: "prepend", target: target, **options + end + end + end + + test "broadcasting action later with multiple ActiveModel targets" do + options = { partial: "messages/message", locals: { message: "hello!" } } + + one = Message.new(id: 1) + targets = [one, "messages"] + expected_targets = "#messages_message_1" + + assert_broadcast_on "stream", turbo_stream_action_tag("prepend", targets: expected_targets, template: render(options)) do + perform_enqueued_jobs do + Turbo::StreamsChannel.broadcast_action_later_to \ + "stream", action: "prepend", targets: targets, **options + end + end + end test "broadcasting render now" do assert_broadcast_on "stream", turbo_stream_action_tag("replace", target: "message_1", template: "Goodbye!") do