Skip to content

Instantly share code, notes, and snippets.

@leastbad
Last active July 24, 2022 11:10
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save leastbad/7c5f2896d4ab3002ee2e18efbc6861d5 to your computer and use it in GitHub Desktop.
Save leastbad/7c5f2896d4ab3002ee2e18efbc6861d5 to your computer and use it in GitHub Desktop.
Action Cable Channels setup
module ApplicationCable
class Channel < ActionCable::Channel::Base
include CableReady::Broadcaster
delegate :render, to: :ApplicationController
end
end
module ApplicationCable
class Connection < ActionCable::Connection::Base
identified_by :session_id, :current_user
def connect
env["warden"].authenticated?
self.current_user = env["warden"].user
self.session_id = request.session.id
# this assumes that you want to enable SR for unauthenticated users
reject_unauthorized_connection unless current_user || session_id
# if you want to disable SR for unauthenticated users, comment out the line above and uncomment the line below
# reject_unauthorized_connection unless current_user
end
end
end
# frozen_string_literal: true
class Users::RegistrationsController < Devise::RegistrationsController
def create
old_session_id = session.id.to_s
build_resource(sign_up_params)
resource.save
if resource.persisted?
session.options[:id] = session.instance_variable_get(:@by).generate_sid
session.options[:renew] = false
set_flash_message! :notice, :signed_up
sign_up(resource_name, resource)
cable_ready[SessionsChannel].dispatch_event(name: "reconnect").broadcast_to(request.session.id)
ActionCable.server.remote_connections.where(session_id: old_session_id, current_user: nil).disconnect
respond_with resource, location: after_sign_up_path_for(resource)
else
clean_up_passwords resource
set_minimum_password_length
respond_with resource, status: 400
end
end
end
import CableReady from 'cable_ready'
import consumer from './consumer'
let reconnecting = false
consumer.subscriptions.create('SessionChannel', {
received (data) {
if (data.cableReady)
CableReady.perform(data.operations, {
emitMissingElementWarnings: false
})
},
connected () {
reconnecting = false
document.addEventListener('reconnect', this.reconnect)
},
disconnected () {
document.removeEventListener('reconnect', this.reconnect)
if (reconnecting) setTimeout(() => consumer.connect(), 25)
},
reconnect () {
reconnecting = true
consumer.disconnect()
}
})
class SessionChannel < ApplicationCable::Channel
def subscribed
stream_for session_id
end
end
# frozen_string_literal: true
class Users::SessionsController < Devise::SessionsController
def create
prev_session_id = session.id.to_s
super do
session.options[:id] = session.instance_variable_get(:@by).generate_sid
session.options[:renew] = false
cable_ready[SessionsChannel].dispatch_event(name: "reconnect").broadcast_to(request.session.id)
ActionCable.server.remote_connections.where(session_id: prev_session_id, current_user: nil).disconnect
end
end
def destroy
prev_session_id = session.id.to_s
old_user = current_user
signed_out = (Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name))
set_flash_message! :notice, :signed_out if signed_out
cable_ready[SessionsChannel].dispatch_event(name: "reconnect").broadcast_to(request.session.id)
ActionCable.server.remote_connections.where(session_id: prev_session_id, current_user: old_user).disconnect
redirect_to after_sign_out_path_for(resource_name)
end
private
def verify_signed_out_user
if all_signed_out?
set_flash_message! :notice, :already_signed_out
redirect_to after_sign_out_path_for(resource_name)
end
end
end
import consumer from './consumer'
import CableReady from 'cable_ready'
let channel
document.addEventListener('turbo:load', () => {
if (channel) return
channel = consumer.subscriptions.create('UsersChannel', {
received (data) {
if (!data) channel = undefined
if (data.cableReady) CableReady.perform(data.operations)
}
})
})
class UsersChannel < ApplicationCable::Channel
def subscribed
if current_user
stream_for current_user
else
transmit false
reject
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment