Search code examples
ruby-on-railsturbo

Rails turbo stream


I am confused why i dont get 2 entries when i create a new quote with the following code.

My thought is that i would get an entry from the following:

  1. the create method that returns the turbo_stream and renders the create.turbo_stream
  2. the actionCable that im subscribed to.

if i remove the stream, i still get just 1 entry. if i remove the append method in create.turbo_stream, i still get one entry ( from the cable)

WHY DONT I GET 2 with both enabled?

controller: In create i have a response type of format.turbo_stream.erb along with the html response type.

create.turbo_stream.erb:

<%= turbo_stream.prepend "quotes", @quote %>
<%= turbo_stream.update Quote.new, "" %>

View

<%= turbo_stream_from( [current_company, "quotes"] ) %>

Quote model broadcast:

  broadcasts_to ->(quote) { [quote.company, "quotes"] }, inserts_by: :prepend

Solution

  • You've skipped the important part, the partial that you're rendering:

    # app/views/quotes/_quote.html.erb
    
    <div id="<%= dom_id(quote) %>">
      <%= quote.content %>
    </div>
    

    Both of these:

    turbo_stream.prepend "quotes", @quote
    
    broadcasts_to ->(quote) { [quote.company, "quotes"] }, inserts_by: :prepend
    

    eventually render a turbo_stream_action_tag that uses the _quote partial as a template:

    <turbo-stream action="prepend" target="quotes">
      <template>
        <div id="quote_1"> q1 </div>
      </template>
    </turbo-stream>
    

    On the front end, turbo processes that tag and prepends the template to the specified target #quotes:

    <div id="quotes">
      <div id="quote_1"> q1 </div>
    </div>
    

    Turbo prepend and append actions take the id of direct child nodes into account and replace them instead.

    If you want to get duplicates, just wrap everything in a tag:

    # app/views/quotes/_quote.html.erb
    
    <div>
      <div id="<%= dom_id(quote) %>">
        <%= quote.content %>
      </div>
    </div>
    

    However, doing that will mess up the replace action by forever nesting div.


    If the template’s first element has an id that is already used by a direct child inside the container targeted by dom_id, it is replaced instead of prepended.

    https://turbo.hotwired.dev/reference/streams#prepend