Rails HTML Polling Without Writing JavaScript?
Published Last updated loading views
Write simple HTML polling by writing Ruby on Rails ONLY.
If you did Rails, youâve probably coded one or two polling mechanisms back in the day. Midway through writing it, an annoying feeling starts creeping in when you have to write that extra JavaScript after coding the Rails part on the server. If you get that feeling, (and even if you donât), there is now a way to do it without actually writing any JS code. First, letâs dive into idea of polling below.
What is polling?
Polling is a process when a client (our browser in this case) continually sends requests to a server to check if updates are available. Polling is what is called pull technology. Itâs often used to emulate push technology. Before we go on, letâs describe these terms:
Pull technology
Definition: Initial request for data originates from a client, and then is responded to. Example: A web browser requests a web page.
Push technology (also known as push notifications)
Definition: A server publishes data, and a client that is subscribed is receiving data. Example: A email server transmits an email to an email client.
So, instead of doing publish / subscribe mechanism, where the server sends data updates and we listen for those updates, we are going to repeatedly ask the server whether changes did actually happen.
How to do polling in Rails?
OK, now that we explained what polling is, letâs get down to business. In order to do polling in Rails you will need to write 2 things:
- Controller action that will be polled and the response/view it returns
- JavaScript that will periodically check your controller action for changes and make necessary updates in the UI
First part is pretty straightforward. Letâs say we have a website that showâs movies and their ratings. Rating of a movie changes constantly, and we want to keep the user updated for any rating change that happens. For this case, we will create a rating action inside the Movies controller.
# app/controllers/movies_controller.rb
class MoviesController < ApplicationController
# somewhere inside Movies controller
def rating
@rating = @movie.rating
render partial: 'movie_rating'
end
end
Then, we can create a partial for the movie rating like this, so we can show it nicely to the user:
<!-- app/views/movies/_movie_rating.html.erb -->
Movie rating: <%= @rating %>
Second part can be a little annoying sometimes. We need to write JavaScript on our frontend that will continuously query the server action we defined. But, it also needs to update the page so the changes can be reflected.
<!-- app/views/movies/show.html.erb -->
<div id="rating">Loading rating...</div>
<script>
const checkRating = () => {
fetch("<%= movie_rating_path(@movie) %>")
.then((response) => response.text())
.then((response) => {
document.getElementById("rating").innerHTML = response
})
}
setInterval(checkRating, 2000)
</script>
Here we defined a checkRating (line 6) function that will get called every 2 seconds by the setInterval at line 14. On the line 7, we are telling it to fetch a rating of a movie by specifying its ID in the request URL.
And voilĂ đ, if you go to your movie page and open the Network tab in your browser, you should see that request towards rating action is dispatched every 2 seconds.
But how do I poll without JavaScript?
Hold your horses đ , we are getting there. You can do simple polling with the new version of the render_async gem! In order to do this, youâll need to install the gem inside your Rails application and put this snippet in your application.html.erb file.
<%= content_for :render_async %>
This snippet will load the JavaScript code for us so that we donât have to write it ourselves. So, itâs not exactly without it, itâs just that we donât have to write it ourselves.
We will keep movies_controller.rb and _movie_rating.html.erb files from the previous example, and we will only edit show.html.erb to look like this:
<!-- app/views/movies/show.html.erb -->
<%= render_async movie_rating_path(@movie), interval: 2000 %>
Wait, that is it? Yep, thatâs it, congrats đ! This piece of code will generate JavaScript that will fetch movie rating every 2 seconds. How neat and awesome đ. If you visit your movie page now, its rating should show up and should constantly be updated by polling.
BONUS ROUND
Thatâs not all you can do with it. You can throw in some error handling in there too, also without any JS code to be written:
<!-- app/views/movies/show.html.erb -->
<%= render_async movie_rating_path(@movie), interval: 2000, error_message:
"Couldn't load rating :(" %>
Your reaction while reading this: WOW, I can get an error message to show up too � Where can I try out this gem?
Right here my friend. Youâre welcome â¤ď¸.
Polling feature was recently released in the 2.1.0 version of the gem and itâs ready to be used by the community. If you are using polling in your app, you can try out this feature of the gem.
render_async has been around for a long time, itâs used in products like Codetriage (see issue on GitHub by Richard Schneeman and itâs been praised by Nate Berkopec on Twitter:
I think render_async looks like another potential valuable part of the "html-over-the-wire" toolkit, along with PJAX and Turbolinks.
— Nate Berkopec (@nateberkopec) June 8, 2017
You can also read the original blog post that made render_async famous and see his original use case on the Semaphore CI blog.
If you liked what you saw, please đ and spread the word. Also, check out my website and follow me. Iâll be posting more of Rails and JavaScript related articles, so click âFollowâ and stay tuned đš.
Also, retweeting this is an awesome way to help spread the word with your friends:
I just published âRails HTML Polling Without JavaScriptâ #rails #javascript https://t.co/vbO9CgStV8
— Nikola Äuza (@nikolalsvk) May 14, 2019
Cheers! đť
This article was originally posted on Medium
Join the newsletter!
Subscribe to get latest content by email and to become a fellow pineapple đ