Skip to content

Commit 00cae6a

Browse files
authored
Document how to extend turbo_stream for custom actions (hotwired#555)
Closes [hotwired#554][] The current `Turbo::Streams::TagBuilder` class supports the actions that Turbo provides out of the box. For applications that define [Custom Stream Actions][], this new support aims to provide them with a mechanism to define Rails-side helpers. For example, consider an `[action="highlight"]` custom stream. To build those with first-party tooling, applications could add a [hook block][] to their initializer: ```ruby # config/initializers/turbo.rb ActiveSupport.on_load :turbo_streams_tag_builder do def highlight(target) action :highlight, target end def highlight_all(targets) action_all :highlight, targets end end turbo_stream.highlight "my-element" # => <turbo-stream action="highlight" target="my-element"><template></template></turbo-stream> turbo_stream.highlight_all ".my-selector" # => <turbo-stream action="highlight" targets=".my-selector"><template></template></turbo-stream> ``` [hotwired#554]: hotwired#554 [Custom Stream Actions]: https://turbo.hotwired.dev/handbook/streams#custom-actions [hook block]: https://edgeapi.rubyonrails.org/classes/ActiveSupport/LazyLoadHooks.html#method-i-on_load
1 parent 38a7ca6 commit 00cae6a

File tree

3 files changed

+39
-0
lines changed

3 files changed

+39
-0
lines changed

app/models/turbo/streams/tag_builder.rb

+20
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,24 @@
2222
# <%= turbo_stream.append dom_id(topic_merge) do %>
2323
# <%= link_to topic_merge.topic.name, topic_path(topic_merge.topic) %>
2424
# <% end %>
25+
#
26+
# To integrate with custom actions, extend this class in response to the :turbo_streams_tag_builder load hook:
27+
#
28+
# ActiveSupport.on_load :turbo_streams_tag_builder do
29+
# def highlight(target)
30+
# action :highlight, target
31+
# end
32+
#
33+
# def highlight_all(targets)
34+
# action_all :highlight, targets
35+
# end
36+
# end
37+
#
38+
# turbo_stream.highlight "my-element"
39+
# # => <turbo-stream action="highlight" target="my-element"><template></template></turbo-stream>
40+
#
41+
# turbo_stream.highlight_all ".my-selector"
42+
# # => <turbo-stream action="highlight" targets=".my-selector"><template></template></turbo-stream>
2543
class Turbo::Streams::TagBuilder
2644
include Turbo::Streams::ActionHelper
2745

@@ -246,4 +264,6 @@ def render_record(possible_record)
246264
@view_context.render(partial: record, formats: :html)
247265
end
248266
end
267+
268+
ActiveSupport.run_load_hooks :turbo_streams_tag_builder, self
249269
end
+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
ActiveSupport.on_load :turbo_streams_tag_builder do
2+
def highlight(target)
3+
action :highlight, target
4+
end
5+
6+
def highlight_all(targets)
7+
action_all :highlight, targets
8+
end
9+
end

test/streams/streams_helper_test.rb

+10
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
class TestChannel < ApplicationCable::Channel; end
44

55
class Turbo::StreamsHelperTest < ActionView::TestCase
6+
attr_accessor :formats
7+
68
test "with streamable" do
79
assert_dom_equal \
810
%(<turbo-cable-stream-source channel="Turbo::StreamsChannel" signed-stream-name="#{Turbo::StreamsChannel.signed_stream_name("messages")}"></turbo-cable-stream-source>),
@@ -33,4 +35,12 @@ class Turbo::StreamsHelperTest < ActionView::TestCase
3335
turbo_stream_from("messages", channel: "NonExistentChannel", data: {payload: 1})
3436
end
3537

38+
test "custom turbo_stream builder actions" do
39+
assert_dom_equal <<~HTML.strip, turbo_stream.highlight("an-id")
40+
<turbo-stream action="highlight" target="an-id"><template></template></turbo-stream>
41+
HTML
42+
assert_dom_equal <<~HTML.strip, turbo_stream.highlight_all(".a-selector")
43+
<turbo-stream action="highlight" targets=".a-selector"><template></template></turbo-stream>
44+
HTML
45+
end
3646
end

0 commit comments

Comments
 (0)