Categories
Web Development

CableReady is Magic

CableReady makes it possible to create a real-time updating dashboard with zero Javascript written by you. With CableReady you can have an ActiveJob render an updated partial and then tell CableReady to update the div with the new HTML.

For our example, let’s say we have an application that executes a task every minute that makes a call to a Twitter API to search for tweets that contain a keyword. If there are new results found, we want to update the user’s dashboard that created the search.

The first thing you need to do is add CableReady to your project using bundler and yarn:

bundle add cable_ready
yarn add cable_ready

We only want the updates to go to the user that created the search. You can do that by creating a UserChannel and setting the stream_for name with the signed in users id.

Create the channel with the following command:

bundle exec rails generate channel user

Edit the auto generated user_channel and rename the stream_for to include the id of the current logged in user.

app/channels/user_channel.rb
class UserChannel < ApplicationCable::Channel
  def subscribed
    stream_for "user_channel_#{current_user.id}"
  end
end

Edit the user_channel.js JavaScript to include the CableReady magic.

app/javascript/channels/user_channel.js
import CableReady from 'cable_ready'
import consumer from './consumer'
​
consumer.subscriptions.create('UserChannel', {
  received (data) {
   if(data.cableReady) CableReady.perform(data.operations)
  }
})

In our dashboard view, simply render a partial and make sure you wrap it in a div tag.

app/views/dashboard.html.erb
<div id="dashboard_tweets">
  <%= render partial: "tweets", locals: {tweets: @tweets} %> 
</div>

In our ActiveJob code, make sure you include the CableReady broadcaster . We then make a call to fetch the new tweets from our Twitter API.

Then the magic comes into play, we render the updated partial in our job and send it over the WebSocket using Cable Ready.

We do this by giving cable ready our user channel name we created above and include the user id of the person who owns the search. We tell it to replace the inner_html of the given selector of our dashboard_tweets div with the HTML partial we rendered in tweets_html.

app/jobs/fetch_tweets_job.rb
class FetchTweetsJob < ApplicationJob
  include CableReady::Broadcaster
  queue_as :default

   def perform(search_id)
     search = Search.find(search_id)
     tweets = search.fetch_new_tweets
     
    # Render the HTML Partial with the new data from tweets
     tweets_html = ApplicationController.renderer.render(
          partial "dashboard/tweets", 
          locals" { tweets: tweets})

    # Tell CableReady what to update
     cable_ready["user:user_channel_#{search.user_id}"].inner_html(
       selector: "#dashboard_tweets",
       html: tweets_html
     )
    
    # Broadcast the changes. 
     cable_ready.broadcast
end 

That’s it as soon as you sent the cable_ready.broadcast command the users dashboard will be updated automatically.

For more information on all of the awesome things you can do with CableReady, check out the documentation at https://cableready.stimulusreflex.com/.

If you need help using CableReady, feel free to comment below!