How do you stream a broadcast to a specific user in Rails 5 with ActionCable?
Asked Answered
L

2

5

I have 2 user types in my application (worker and company). Both user types are created with Devise. I'm currently trying to send a notification to a specific company with ActionCable.

My main problem is that when I send a notification every single company that's signed in receives it. I get that I'm supposed to include the company id in the stream name in some way, but I haven't had any luck so far.

I've included the working code that sends notifications to all companies below:

notifications_channel.rb

class NotificationsChannel < ApplicationCable::Channel
  def subscribed
    stream_from "notifications_channel"
  end

  def unsubscribed
    # Any cleanup needed when channel is unsubscribed
  end
end

connection.rb

module ApplicationCable
  class Connection < ActionCable::Connection::Base
  end
end

Call to the broadcast

ActionCable.server.broadcast 'notifications_channel', { 'My data' }

EDIT

I log the status of the notification with javascript:

notifications.js

App.notifications = App.cable.subscriptions.create("NotificationsChannel", {
  connected: function() {
    console.log("connected");
  };

  disconnected: function() {
    console.log("disconnected");
  };

  received: function(data) {
    console.log("recieved");
  };
});
Lw answered 27/11, 2018 at 3:24 Comment(0)
W
8

Broadcast the message from your controller like this:

# Broadcast your message
ActionCable.server.broadcast "notifications_channel:#{target_user.id}

Now Update app/channels/application_cable/connection.rb with the below code

module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user

    def connect
      self.current_user = find_verified_user
      logger.add_tags 'ActionCable', current_user.name
    end

    protected

    def find_verified_user
      verified_user = User.find_by(id: cookies.signed['user.id'])
      if verified_user && cookies.signed['user.expires_at'] > Time.now
        verified_user
      else
        reject_unauthorized_connection
      end
    end
  end
end

And subscribe to the stream like this:

def subscribed
  stream_from "notifications_channel:#{current_user.id}"
end

Note: This is just an example to show how to target a specific user in Actioncable. You may have to modify the code based on your requirement.

I also recommend watching this video by GoRails.

Wilsey answered 27/11, 2018 at 4:26 Comment(5)
Thanks for the input. I've updated my question with the JS file I use to track the status of the notification. With your code I get the "disconnected" status. Any idea why?Lw
Please provide a screenshot of your log also.Wilsey
if you need further help we can continue the discussion here chat.stackoverflow.com/rooms/184302/…Wilsey
I have to use syntax like "notifications_channel_#{current_user.id}" to make it work, it does not work with ":"Saddlecloth
@Saddlecloth Thanks, That's an interesting find!! I will update my answer based on your comment or feel free to edit my answer.Wilsey
L
1

I managed to find the solution. Following Abhilashs answer took me most of the way, but I still had trouble authenticating the company. It seems like Warden was not fully configured, so this post made it work: env['warden'] not working with Rails 5

Lw answered 27/11, 2018 at 14:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.