HotWire
Install rails
rails g scaffold Post title:string body:text rails db:create RAILS_ENV=development rails db:migrate RAILS_ENV=development
Install hotwire
gem 'hotwire-rails' bundle install rails hotwire:install
Step 1: set broadcast section before any action
Go to Post Model then add this code: after_create_commit {broadcast_prepend_to "posts"}
Step 2: We need to create frame in poxts/index and use same name “posts” 1- Go to the posts/index view.
2- Add this code.
‘’’
<%= turbo_frame_tag "posts" do %>
<%= render @posts %>
<% end %>
‘’’
That will create tag <turbo-frame id="posts">
.
3- Add this style: “app/assets/stylesheets/application.css”, to notice where this tag set. ‘’’ turbo-frame { border: 1px solid red; padding: 2rem; display: block; } ‘’’
4- Go to `app/controllers/posts_controller.rb#create’ change the successful creation part From
format.html { redirect_to @post, notice: 'Post was successfully created.' }
To
format.html { redirect_to posts_url, notice: 'Post was successfully created.' }
Step 3: Let’s test create a new post:
Processing by PostsController#create as TURBO_STREAM
[ActionCable] Broadcasting to posts: "<turbo-stream action=\"prepend\" target=\"posts\"><template><div>\n <h3>Test title</h3>\n <p>test body</p>\n <a href=\"/posts/9\">Show</a>\n <a href=\"/posts/9/edit\">Edit</a>\n <a data-confirm=\"Are you sure?\" rel=\"nofollow\" data-method=\"delete\" href=\"/posts/9\">Destroy</a>\n</div>\n<hr/>\n</template></turbo-stream>"
- We have normal redirect
Redirected to http://localhost:3000/posts
- Processing by PostsController#index as TURBO_STREAM // only happen after creation TURBO_STREAM
?? Backend broadcast the new changes , but nothing in the frontend handle this event
Step 4: Add this line in posts/index
view:
<%= turbo_stream_from “posts” %>
Adding a tube stream from
will set up a line of code in Html, that says “
javascript go and stream form “posts stream” , to that tell the action cable channel to stream the that channel
Model:post after_create_commit {broadcast_prepend_to "posts”}.
If we check the html Code ‘’’ ‘’’ Steam tag is going to be monitored and start the stream and close the stream, whenever you move a way from that page
Let’s test this changes Example 1:
- Go to Rials console
- Post.create title: "Hotwire", body: "Hotwire is an alternative approach to building modern web applications without using much JavaScript by sending HTML instead of JSON over the wire" Example 2: add these lines of code in the Models/Post: after_update_commit {broadcast_replace_to "posts"} after_destroy_commit {broadcast_remove_to "posts"}
And from Rails console try to destroy:
- Post.last.destroy
- Post.last.update body: "Hey"
We will notice there is no change, why!! , let’s check the log file.
Turbo::StreamsChannel transmitting "<turbo-stream action="remove" target="post_22">" (via streamed from posts) | target="post_22" Frontend going to search this Dom id, but it’s not exist Step 5: We need to wrap our code with turbo_frame_tag “app/views/posts/_post.html.erb”
<%= turbo_frame_tag dom_id(post) do %>
……
<% end %>
Check html code
<turbo-frame id="post_1"></turbo-frame>
<%= turbo_frame_tag post do %>
……
<% end %>
Check html code
Step 6: Handling Post in the form: 1- wrap the form prat with in the posts/index
<%= turbo_frame_tag ‘post_form’ do %>
<%= render 'form', post: @post %>
<% end %>
Try to submit invalid data ( empty form) nothing happen , if we check the log file,
Processing by PostsController#create as TURBO_STREAM Rails nothing happen becuse we don’t handle this TURBO_STREAM in the controller 2- Go to `app/controllers/posts_controller.rb#create’
format.turbo_stream { render turbo_stream: turbo_stream.replace(@post, partial: "posts/form", locals: { post: @post}) }
3- Go to ‘app/views/posts/_form.html.erb’
<%= form_with(model: post, local: true, id: dom_id(post)) do |form| %>
If it a new post, form id = ‘new_post’ If it a exist post, form id = ‘post_1’ Check (chrome , console , network)
Check these file: app/models/concerns/turbo/broadcastable.rb #model function app/assets/javascripts/turbo.js (StreamActions: prepend/ append/ remove/update)