I am new to Ruby on Rails and need help with figuring out how Turbo Stream works in Rails. I did everything by tutorials, however, the content of the page was not updating. I decided to test how Turbo Stream will behave on simple div.
In index.html.erb
file I created such div with id="test"
:
<div id = "test">Hallow</div>
In the same file I am creating a button that calls method refresh
in controller.
<%=button_to " ", refresh_path(:task => task, format: :turbo_stream)%>
The method is called and works properly, I have already checked it without Turbo Stream.
The content of refresh.turbo_stream.erb
:
<%= turbo_stream.replace 'test', partial: 'refresh' %>
The content of _refresh.html.erb
<h1>GoodBye</h1>
Here is the proof that Turbo Stream works
Indeed Turbo Stream renders the page, but I get such an output.
I tried writing respond in controller, deleting turbo_stream format (it caused another error), playing with routes, but did not come up to anything.
I am sorry if this question might have been answered already, but I tried different options and nothing worked for me. Please help!
Turbo doesn't process links with formats other than html (apparently php as well).
So when you click a link or a button, that has ".json", ".xml", or ".turbo_stream" or anything else, Turbo gives up and just sends you directly to that page where browser displays it the best it can, and it knows nothing about what to do with turbo_stream, which has Content-Type: text/vnd.turbo-stream.html
, so, plain text in the browser.
To fix it, remove :format
:
<%= button_to "refresh", refresh_path(task: task) %>
With this button, Turbo will send a correct request, where it will wait for html or turbo_stream response, which you can see in the request header:
Accept: text/vnd.turbo-stream.html, text/html, application/xhtml+xml
If the server then responds with turbo_stream format: Content-Type: text/vnd.turbo-stream.html
then stream instructions will execute on the current page. There are other rules, but one step at a time.
To render an appropriate response use respond_to
method in your controller action:
respond_to do |format|
format.html { render :page } # renders `page.html.erb`
format.turbo_stream { render :page } # renders `page.turbo_stream.erb`
# or render <turbo-stream> inline
# format.turbo_stream { render turbo_stream: turbo_stream.replace :test, partial: "test_partial" }
end