How do I render the show action on update.turbo_stream

When I update an invoice I want to render the full invoice page again. I do not want to render @invoice using _invoice.html.erb as it is set up specifically to render out for the index action. The show page is what has the invoice details in it. When I update an invoice I am getting a missing template error. What am I doing wrong?

Here is my update.turbo_stream.erb:

<%= turbo_stream.replace(@invoice, partial: "show", target: "_top", locals: {invoice: @invoice, client: @client}) %>

  def update
    respond_to do |format|
      if @invoice.update(invoice_params)
        format.turbo_stream
        format.html { redirect_to invoice_path(@invoice) }
        format.json { render :show, status: :ok, location: @invoice }
      else
        format.html { render :edit, status: :unprocessable_entity }
        format.json { render json: @invoice.errors, status: :unprocessable_entity }
      end
    end
  end

You need to use the full view path. For example, assuming the path to the partial is app/views/invoice/show.html.erb, you then use

<%= turbo_stream.replace @invoice, partial: "invoice/show", target: "_top", locals: {invoice: @invoice, client: @client} %>

or

<%= turbo_stream.replace @invoice, target: "_top" %>
	<%= render "invoice/show" locals: {invoice: @invoice, client: @client} %>
<% end %>

I prefer the latter format as it clearly separates the turbo-stream tag options from the rest of the html.

I also recommend using redirect in responding to successful json format

  def update
    respond_to do |format|
      if @invoice.update(invoice_params)
        format.turbo_stream
        format.html { redirect_to invoice_path(@invoice) }
-       format.json { render :show, status: :ok, location: @invoice }
+       format.json { redirect_to invoice_path(@invoice, format: :json) }
      else
        format.html { render :edit, status: :unprocessable_entity }
        format.json { render json: @invoice.errors, status: :unprocessable_entity }
      end
    end
  end

Thanks. When I set it up like you mentioned I still get the same error:

12:51:01 web.1 | ActionView::Template::Error (Missing partial invoices/_show with {:locale=>[:en], :formats=>[:turbo_stream, :html], :variants=>, :handlers=>[:raw, :erb, :html, :builder, :ruby, :jbuilder]}.

<%= turbo_stream.replace @invoice, target: "_top" do %>
	<%= render "invoices/show", locals: {invoice: @invoice, client: @client} %>
<% end %>

Sorry, I meant to write

You need to use the full view path. For example, assuming the path to the partial is app/views/invoice/_show.html.erb , you then use

From Rails documentation:

partials are named with a leading underscore to distinguish them from regular views, even though they are referred to without the underscore. This holds true even when you’re pulling in a partial from another folder:

Which is why the error reports

Missing partial invoices/_show

Your file structure could look something like

app/views/invoice/_show.html.erb (partial)

my partial

app/views/invoice/show.html.erb (view)

<%= render "invoice/show" locals: {invoice: @invoice, client: @client} %>

app/views/invoice/update.turbo_stream.erb (turbo stream)

<%= turbo_stream.replace @invoice, target: "_top" %>
	<%= render "invoice/show" locals: {invoice: @invoice, client: @client} %>
<% end %>
1 Like

Ahhh thanks. That makes sense. I got it working following your info. Thanks!

Rezzing this thread as it came up multiple times in searching for a solution to the same(ish) problem.

I’m looking to render the show view from my update.turbo_stream.erb. Is there a way to tell turbo streams “Use this view,” instead of a partial?

I am otherwise looking at shoving the entirety of the view into _show.html.erb, and then making a one-line render call to the partial-thats-actually-everything in show.html.erb.

…which I can do, and does work, but just feels janky and wrong.

2 Likes