Skip to content

Commit

Permalink
Document how to extend turbo_stream for custom actions (hotwired#555)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
seanpdoyle authored Jan 12, 2024
1 parent 38a7ca6 commit 00cae6a
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 0 deletions.
20 changes: 20 additions & 0 deletions app/models/turbo/streams/tag_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,24 @@
# <%= turbo_stream.append dom_id(topic_merge) do %>
# <%= link_to topic_merge.topic.name, topic_path(topic_merge.topic) %>
# <% end %>
#
# To integrate with custom actions, extend this class in response to the :turbo_streams_tag_builder load hook:
#
# 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>
class Turbo::Streams::TagBuilder
include Turbo::Streams::ActionHelper

Expand Down Expand Up @@ -246,4 +264,6 @@ def render_record(possible_record)
@view_context.render(partial: record, formats: :html)
end
end

ActiveSupport.run_load_hooks :turbo_streams_tag_builder, self
end
9 changes: 9 additions & 0 deletions test/dummy/config/initializers/turbo.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
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
10 changes: 10 additions & 0 deletions test/streams/streams_helper_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
class TestChannel < ApplicationCable::Channel; end

class Turbo::StreamsHelperTest < ActionView::TestCase
attr_accessor :formats

test "with streamable" do
assert_dom_equal \
%(<turbo-cable-stream-source channel="Turbo::StreamsChannel" signed-stream-name="#{Turbo::StreamsChannel.signed_stream_name("messages")}"></turbo-cable-stream-source>),
Expand Down Expand Up @@ -33,4 +35,12 @@ class Turbo::StreamsHelperTest < ActionView::TestCase
turbo_stream_from("messages", channel: "NonExistentChannel", data: {payload: 1})
end

test "custom turbo_stream builder actions" do
assert_dom_equal <<~HTML.strip, turbo_stream.highlight("an-id")
<turbo-stream action="highlight" target="an-id"><template></template></turbo-stream>
HTML
assert_dom_equal <<~HTML.strip, turbo_stream.highlight_all(".a-selector")
<turbo-stream action="highlight" targets=".a-selector"><template></template></turbo-stream>
HTML
end
end

0 comments on commit 00cae6a

Please sign in to comment.