0

In my Ruby on Rails project, I have a user model that is set up by devise. Each user belongs to an account with an account_id.

In my application_controller.rb I have

def set_account
  @account = current_user.account
end

This is working fine as in many places of my project I have before_action: set_account and it does assign @account correctly.

When a user signs in, I want the user to subscribe to message_notifications_channel_#{account_id} where account_id is the id of the account that the user belongs to.

This is how I set up connection.rb:

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

  def connect
    self.current_user = find_verified_user
  end

  private
  def find_verified_user
    if verified_user = User.find_by(id: cookies.encrypted[:user_id])
      verified_user
    else
      reject_unauthorized_connection
    end
  end
end

end

When I entered byebug here, User.find_by(id: cookies.encrypted[:user_id]) returned nil and cookies.encrypted[:user_id] is nil too.

This is the setup for message_notifications_channel.rb:

class MessageNotificationsChannel < ApplicationCable::Channel
  def subscribed
    current_user.appear
    # stream_from "some_channel"
    stream_from "message_notifications_channel_#{params[:account_id]}"
  end

  def unsubscribed
    current_user.disappear
    # Any cleanup needed when channel is unsubscribed
  end
end

For message_notifications.coffee, this is the code:

App.message_notifications = App.cable.subscriptions.create {channel: "MessageNotificationsChannel", account_id: current_user.account_id},
  connected: ->
    # Called when the subscription is ready for use on the server

  disconnected: ->
    # Called when the subscription has been terminated by the server

  received: (data) ->
    # Called when there's incoming data on the websocket for this channel
    if data['direction'] == 'incoming'
      ding = new Audio('/assets/ding.wav');
      ding.play();
      $('#conversation-messages').append String(data['message']);
    if data['direction'] == 'outgoing'
      if $('#message_'+data['id']).length == 0
        iphone_sms_sent_sound = new Audio('/assets/iphone_send_sms.mp3');
        iphone_sms_sent_sound.play();
        $('#conversation-messages').append String(data['message']);
      else
        $('#message_'+data['id']).replaceWith(data['message']);

I'm using the following to broadcast message in the after_create callback of Message.rb:

ActionCable.server.broadcast "message_notifications_channel_#{self.account_id}", {id: self.id, direction: self.direction, message: ApplicationController.render(partial:'inbox/message', locals: {message: self})}

This would not work and I got "An unauthorized connection attempt was rejected". I tried using App.message_notifications = App.cable.subscriptions.create {channel: "MessageNotificationsChannel", account_id: @account.id} This would not work either. Then I did App.message_notifications = App.cable.subscriptions.create {channel: "MessageNotificationsChannel", account_id: 3} and commented out current_user.appear and current_user.disappear in message_notifications_channel.rb and everything inside

module ApplicationCable
end

in connection.rb. Then packets will get broadcast and received and things will show up.

How do I get App.message_notifications = App.cable.subscriptions.create {channel: "MessageNotificationsChannel", account_id: }, to use the id of @account.id or current_user.account_id while keeping the methods for user verification in connection.rb? Thanks!

jl118
  • 307
  • 2
  • 16
  • I am pretty bad with actioncable and I am still trying to find out how to solve my own case. But your problem should come from the `connection.rb` file. Your connection is just rejected. One guess is that you try to get the user from `cookies` whereas it should be stored in `session`. Also if User is a devise model you can grab it directly through warden when the user is logged : `if verified_user = env["warden"].user` For the rest of your question I can't really help. sorry. – Maxence Sep 25 '18 at 23:08
  • Thanks! Indeed, doing `env['warden'].user` solved the problem and `current_user ` can be found in other parts of the app. – jl118 Sep 28 '18 at 18:52

0 Answers0