Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ActionCable registers user multiple times

I'm using ActionCable in my RoR application designed to function as a chatroom for roleplays, according to Sitepoint's tutorial. I have set it up, and messages are, as expected, broadcasted whenever one is created. However, each time the chat room page is loaded, new subscriptions are made for the same user, making messages appear multiple times.

app/assets/javascripts/channels/roleplays.coffee:

jQuery(document).on 'turbolinks:load', ->
  messages = $('#messages')
  if $('#messages').length > 0


    App.global_chat = App.cable.subscriptions.create {
      channel: "RoleplaysChannel"
      roleplay_id: messages.data('roleplay-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) ->
        messages.append(data)
        console.log(data)


      send_message: (message, roleplay_id) ->
        @perform 'send_message', message: message, roleplay_id: roleplay_id


    $('#new_message').submit (e) ->
      $this = $(this)
      textarea = $this.find('#message_body')
      e.preventDefault()

      if $.trim(textarea.val()).length > 1
        App.global_chat.send_message textarea.val(), messages.data('roleplay-id')
        textarea.val('')

      return false
like image 869
Pim van Leeuwen Avatar asked Nov 17 '25 06:11

Pim van Leeuwen


1 Answers

To avoid duplicate subscriptions, you will need some way of determining whether the user is already connected.

A simple approach might be to do something like the following:

(->
  connected = false

  jQuery(document).on 'turbolinks:load', ->
    messages = $('#messages')

    if $('#messages').length > 0 && !connected
      App.global_chat = App.cable.subscriptions.create {
        channel: "RoleplaysChannel"
        roleplay_id: messages.data('roleplay-id')
      },
        connected: ->
          connected = true

        disconnected: ->
          connected = false

        # …
)()

This will only work for a single roleplay (or chatroom). If the user tries a different roleplay to one they've visited previously, they won't be subscribed to the new one. To fix this, you'll need a way of managing subscriptions.

Something like the following might work:

(->
  connections = []

  addConnection = (id) ->
    connections.push(id)

  removeConnection = (id) ->
    index = connections.indexOf(id)
    connections.splice(index, 1) if index > -1

  connectedTo = (id) ->
    connections.indexOf(id) > -1

  jQuery(document).on 'turbolinks:load', ->
    messages = $('#messages')
    roleplayID = messages.data('roleplay-id')

    if $('#messages').length > 0 && !connectedTo(roleplayID)
      App.global_chat = App.cable.subscriptions.create {
        channel: "RoleplaysChannel"
        roleplay_id: roleplayID
      },
        connected: ->
          addConnection(roleplayID)

        disconnected: ->
          removeConnection(roleplayID)

        # …
)()
like image 114
Dom Christie Avatar answered Nov 18 '25 21:11

Dom Christie



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!