ethayer
ethayer

Reputation: 55

Client unsubscribed from Channel

Is it possible to return the unsubscribed channel 'name' to the unsubscribed method?

When a user unsubscribes from a channel (due to disconnect or navigate away), I need to make sure the client flags are set to a null state. I've created a cleanup method, but I'm unable to find out which channel the cleanup message should be sent to.. since I'm unable to get which channel the unsubscribed method was called from.

class ConversationChannel < ApplicationCable::Channel
  def follow(data)
    stop_all_streams
    conversation = Conversation.find(data['conversation_id'])
    if conversation.is_participant?(current_user)
      stream_from "conversation:#{data['conversation_id']}"
    end
  end

  def unsubscribed
    clear_typing
  end

  ...

  def clear_typing
    # need way to find out conversation_id of the unsubscribed stream
    ActionCable.server.broadcast "conversation:#{data['conversation_id']}", {id: current_user.id, typing: false}
  end
end

Upvotes: 2

Views: 1090

Answers (2)

ethayer
ethayer

Reputation: 55

I think this is a possible solution, though it would be better if I could grab the exact unsubscribed stream if possible:

found this by looking at the stop_all_streams method since it alerted me to the existence of the 'streams' variable.

...
  def unsubscribed
    streams.each do |stream|
      ActionCable.server.broadcast stream[0], {id: current_user.id, typing: false}
    end
  end
...

Upvotes: 1

Dharam Gollapudi
Dharam Gollapudi

Reputation: 6438

I believe the class name is the channel name.

From the ActionCable docs:

# app/channels/appearance_channel.rb
class AppearanceChannel < ApplicationCable::Channel
  def subscribed
    current_user.appear
  end

  def unsubscribed
    current_user.disappear
  end

  def appear(data)
    current_user.appear on: data['appearing_on']
  end

  def away
    current_user.away
  end
end

And the client subscribes as follows:

# app/assets/javascripts/cable/subscriptions/appearance.coffee
App.cable.subscriptions.create "AppearanceChannel",
  # Called when the subscription is ready for use on the server
  connected: ->
    @install()
    @appear()

  # Called when the WebSocket connection is closed
  disconnected: ->
    @uninstall()

  # Called when the subscription is rejected by the server
  rejected: ->
    @uninstall()

  appear: ->
    # Calls `AppearanceChannel#appear(data)` on the server
    @perform("appear", appearing_on: $("main").data("appearing-on"))

  away: ->
    # Calls `AppearanceChannel#away` on the server
    @perform("away")


  buttonSelector = "[data-behavior~=appear_away]"

  install: ->
    $(document).on "page:change.appearance", =>
      @appear()

    $(document).on "click.appearance", buttonSelector, =>
      @away()
      false

    $(buttonSelector).show()

  uninstall: ->
    $(document).off(".appearance")
    $(buttonSelector).hide()

If you look closely, client is subscribing to the channel AppearanceChannel which is the name of the class.

Upvotes: 1

Related Questions