Skip to content

Commit

Permalink
Stream Tag Builder: Support :renderable arguments
Browse files Browse the repository at this point in the history
When passed a valid `:renderable` option (like an object that responds
to `#render_in`), treat that object as both the `<turbo-stream>`
element's template contents _and_ attempt to treat it as the target.

For example, consider a simplified "component" class:

```ruby
class Component
  extend ActiveModel::Naming

  def initialize(id:, content:) = (@id, @content = id, content)
  def render_in(...) = @content
  def to_key = [@id]
end

component = Component.new(id: 1, content: "Hello, world")

turbo_stream.update(component) # => <turbo-stream action="update" target="component_1"><template>Hello, world</template></turbo-stream>
```
  • Loading branch information
seanpdoyle committed Jul 13, 2024
1 parent 41e8561 commit 77b5ab7
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 0 deletions.
2 changes: 2 additions & 0 deletions app/models/turbo/streams/tag_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,8 @@ def action_all(name, targets, content = nil, allow_inferred_rendering: true, **r
private
def render_template(target, content = nil, allow_inferred_rendering: true, **rendering, &block)
case
when target.respond_to?(:render_in)
target.render_in(@view_context, &block)
when content.respond_to?(:render_in)
content.render_in(@view_context, &block)
when content
Expand Down
24 changes: 24 additions & 0 deletions test/streams/streams_helper_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,28 @@ class Turbo::StreamsHelperTest < ActionView::TestCase
<turbo-stream action="highlight" targets=".a-selector"><template></template></turbo-stream>
HTML
end

test "supports valid :partial option objects" do
message = Message.new(id: 1, content: "Hello, world")

assert_dom_equal <<~HTML.strip, turbo_stream.update(message)
<turbo-stream action="update" target="message_1"><template><p>Hello, world</p></template></turbo-stream>
HTML
end

class Component
extend ActiveModel::Naming

def initialize(id:, content:) = (@id, @content = id, content)
def render_in(...) = @content
def to_key = [@id]
end

test "supports valid :renderable option objects" do
component = Component.new(id: 1, content: "Hello, world")

assert_dom_equal <<~HTML.strip, turbo_stream.update(component)
<turbo-stream action="update" target="streams_helper_test_component_1"><template>Hello, world</template></turbo-stream>
HTML
end
end

0 comments on commit 77b5ab7

Please sign in to comment.