hazardco
hazardco

Reputation: 397

Rails ActionCable unsubscribe users when browser close

I'm testing ActionCable with a very simple example. I want to see how many users are connected at a time on a website. Users are not registered in the system. Users are assigned a session variable with a uuid. To make the example as simple as possible I have not included a model or database.

#app/controller/users_controller.rb

class UsersController < ApplicationController 

  def index
    if session[:user].nil?
      session[:user] = SecureRandom.uuid
    end
    @user = session[:user]
    UserBroadcastJob.perform_later @user
    end
  end

Views are very simple

#app/views/users/index.html.erb

<h1>Users</h1>

<div id="users">
  <%= render "user",user: @user %>
</div>

Partial for users:

#app/views/users/_user.html.erb

<div class="user">
  User : <%= user %>
</div>

I use a job to call socket

#app/jobs/user_broadcast_job.rb

class UserBroadcastJob < ApplicationJob
queue_as :default

  def perform(user)
    ActionCable.server.broadcast 'user_channel', message: render_user(user)
  end

  def render_user(user)
    ApplicationController.renderer.render(partial: 'users/user', locals: { user: user })
  end
end

And the channel

App.user = App.cable.subscriptions.create "UserChannel",
connected: ->

disconnected: ->

received: (data) ->
console.log(data)
$("#users").prepend(data.message)

This works correctly. In each browser I open the uuid are connected is visible. As I do not use database for persistence, the first open browser has all the uuid and the rest of the browsers goes n-1 uuid visible. It's not important.

My question is:

If a browser closes, how can I send a message to delete the uuid from the template?

ActionCable does not work with sessions.

Ruby version: 2.4.0 Rails version: 5.1.3 jquery installed via yarn

Thanks!!!!

Upvotes: 2

Views: 3144

Answers (2)

Ajay Bhayani
Ajay Bhayani

Reputation: 577

It will very helpful for you

class AppearanceChannel < ApplicationCable::Channel
  def subscribed
    stream_from "appearance"
    @current_user = User.find(params[:room])
    @current_user.appear
    ActionCable.server.broadcast('appearance',{data: @current_user.appear,action: 'SubscribedList'})
  end

  def unsubscribed
    if @current_user.present? 
      ActionCable.server.broadcast('appearance',{data: @current_user.disappear,action: 'SubscribedList'})
    end
  end

end

You can pass param to subscribe but impossible params with unsubscribe. so store current_user to one variable when you call subscribe and said to for destroy me at unsubscribe side.

Upvotes: 2

Crashtor
Crashtor

Reputation: 1279

You can do this under

  def unsubscribed
    # Any cleanup needed when channel is unsubscribed
  end

in your channels/application_cable/your_channel.rb

Besides, ActionCable does work with sessions, it takes a bit of tweaking though.

If you're serious about testing the concurrency of ActionCable (i.e have serious thoughts about using ActionCable in an upscale production), I would kind of advise you to give up already and plugin anyCable. Will save you a ton of time.

Upvotes: 0

Related Questions