A simple guide to Action Cable

Action cable is the Rails way of implementing WebSockets – with some Rails magic.

Why use it

Usually your client to connects with your server by making requests:

With ActionCable, you create an open connection between your client and yo…


This content originally appeared on DEV Community and was authored by Lucas Kuhn

Action cable is the Rails way of implementing WebSockets - with some Rails magic.

Why use it

Usually your client to connects with your server by making requests:
953F8214-7173-4755-B16E-AB6FC9983223

With ActionCable, you create an open connection between your client and your server, allowing a communication flow:
65223B82-BB95-4D36-8FC0-7EE6B1227ED4

Example:

You have a simple blog - posts and comments - and multiple users reading that post. If one user adds a comment, the other one will never know:
Kapture 2021-05-05 at 22.53.50

But with the open connection from ActionCable, he will receive updates from that posts (the important comments from other people)
Kapture 2021-05-05 at 22.44.44

How to do it

First of all, generate a channel for your Posts. This class will be able to broadcast updates to all clients listening:

rails generate channel posts

Which will create some files for you:

      create    test/channels/posts_channel_test.rb
      create  app/channels/posts_channel.rb
   identical  app/javascript/channels/index.js
   identical  app/javascript/channels/consumer.js
      create  app/javascript/channels/posts_channel.js

Sending messages

We will work with our newly generated posts_channel.rb

We want to specify from which channel to stream, so we can pass the an idparams and ask rails to make a stream for that post:

class PostsChannel < ApplicationCable::Channel
  def subscribed
    post = Post.find(params[:id])
    stream_for post
  end
end

And now, from anywhere in our app, we can call PostsChannel and ask it to broadcast something to anyone listening to that post:

PostsChannel.broadcast_to(@post, @comment.body)

We will add this to our create action, to broadcast the comment to the post channel every time a comment is created:

# app/controllers/comments_controller.rb

def create
  @comment = @post.comments.new(comment_params)
    if @comment.save
      PostsChannel.broadcast_to(@post, @comment.body)
      redirect_to @post, notice: "Comment was successfully created."
    else
      render :new
    end
end

And that does nothing so far, since no one is listening to this broadcast. Moving forward!

Receiving messages

Opinionated setup:

I do not like to create a separate file for every consumer, I prefer to do the connection in script tags in the view. It feels more like a separate front end, where only the views that need a connection create one. To do so, change your app/javascript/channels/consumer.js to expose the action cable:

import { createConsumer } from "@rails/actioncable"

(function() {
  window.App || (window.App = {});
  window.App.cable = ActionCable.createConsumer();
}).call(this);

export default createConsumer()

Note: Exposing the cable was the default according to official docs until Rails 6, where Webpacker was introduced

By default, the generator we used before creates a file in app/javascript/channels/posts_channel.js
This might be bad for some reasons:

  • It it always required, so it always run
  • We might not want to have everyone on our app to try and open a connection, just the ones listening to our post show page

So you can go ahead and delete the created posts_channel.js ?

Now, we can make the listener to our broadcast in the view:

<!-- app/views/posts/show.html.erb -->

<script>
  App.cable.subscriptions.create({ channel: "PostsChannel", id: "<%= @post.id %>" }, {
    connected() {
      console.log("Connected to the channel:", this);
    },
    disconnected() {
      console.log("Disconnected");
    },
    received(data) {
      console.log("Received some data:", data);
    }
  });
</script>

And now, upon opening our blog post page, we can see the connected message on our Console, and some Rails main that enabled this connection on our terminal:
82E5203A-8D8C-494E-8810-0CEACBF4AEAB

The posts:Z2lkOi8vYWN0aW9uY2FibGUtYXBwL1Bvc3QvMg is the name of the channel created by rails when we told it to stream_for post in our posts_channel file.

And you’re done! ?
~Almost~

While the above script received data, it doesn’t show it on the page. We can update it to add the comment to our list upon receiving it:

  App.cable.subscriptions.create({ channel: "PostsChannel", id: "<%= @post.id %>" }, {
    received(comment) {
      el = document.createElement('li');
      el.innerHTML = comment;
      document.querySelector('ul').appendChild(el)
    }
  });

(All functions are optional, I removed the disconnected and connected from here)

And there you go, your app now talks to any browser listening to it via Action Cable:
Kapture 2021-05-05 at 22.44.44

References

Rails Guide:
https://guides.rubyonrails.org/action_cable_overview.html
Heroku Guide:
https://blog.heroku.com/real_time_rails_implementing_websockets_in_rails_5_with_action_cable
Cable.yml Config:
https://github.com/rails/rails/issues/28118
Cable for specific pages:
https://stackoverflow.com/questions/39597665/rails-actioncable-for-specific-pages
https://stackoverflow.com/questions/36438323/page-specific-actioncable
Good JS subscription examples:
https://stackoverflow.com/questions/39597665/rails-actioncable-for-specific-pages
https://samuelmullen.com/articles/introduction-to-actioncable-in-rails-5/
https://stackoverflow.com/questions/36266746/actioncable-not-receiving-data
Usage with ActiveJob
https://www.pluralsight.com/guides/creating-a-chat-using-rails-action-cable
Cable on ReactNative
https://stackoverflow.com/questions/43510021/action-cable-not-receiving-response-on-client
AnyCable
Action Cable vs AnyCable: fight! | Nebulab


This content originally appeared on DEV Community and was authored by Lucas Kuhn


Print Share Comment Cite Upload Translate Updates
APA

Lucas Kuhn | Sciencx (2021-05-06T02:00:19+00:00) A simple guide to Action Cable. Retrieved from https://www.scien.cx/2021/05/06/a-simple-guide-to-action-cable/

MLA
" » A simple guide to Action Cable." Lucas Kuhn | Sciencx - Thursday May 6, 2021, https://www.scien.cx/2021/05/06/a-simple-guide-to-action-cable/
HARVARD
Lucas Kuhn | Sciencx Thursday May 6, 2021 » A simple guide to Action Cable., viewed ,<https://www.scien.cx/2021/05/06/a-simple-guide-to-action-cable/>
VANCOUVER
Lucas Kuhn | Sciencx - » A simple guide to Action Cable. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2021/05/06/a-simple-guide-to-action-cable/
CHICAGO
" » A simple guide to Action Cable." Lucas Kuhn | Sciencx - Accessed . https://www.scien.cx/2021/05/06/a-simple-guide-to-action-cable/
IEEE
" » A simple guide to Action Cable." Lucas Kuhn | Sciencx [Online]. Available: https://www.scien.cx/2021/05/06/a-simple-guide-to-action-cable/. [Accessed: ]
rf:citation
» A simple guide to Action Cable | Lucas Kuhn | Sciencx | https://www.scien.cx/2021/05/06/a-simple-guide-to-action-cable/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.