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
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)
# …
)()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With