# layouts/application.html.erb
<%= action_cable_meta_tag if user_signed_in? %>
# assets/javascripts/cable.js
if ($('meta[name=action-cable-url]').length){
(function() {
this.App || (this.App = {});
App.cable = ActionCable.createConsumer($('meta[name=action-cable-url]').attr('content'));
}).call(this);
}
# assets/javascripts/channels/chat.js
if ($('meta[name=action-cable-url]').length){
App.chat = App.cable.subscriptions.create("ChatChannel", {
connected: function() {
// Called when the subscription is ready for use on the server
},
disconnected: function() {
// Called when the subscription has been terminated by the server
},
received: function(data) {
// Called when there's incoming data on the websocket for this channel
$('.messages').prepend(data['message']);
},
});
}
# app/channels/application_cable/connection.rb
module ApplicationCable
class Connection < ActionCable::Connection::Base
identified_by :current_user
def connect
self.current_user = find_verified_user
end
protected
def find_verified_user
if verified_user = env['warden'].user
verified_user
else
reject_unauthorized_connection
end
end
end
end
# User Logs On (typically in a session#new)
# cookies.signed['user.id'] = user.id
# cookies.signed['user.expires_at'] = 30.minutes.from_now
# ActionCable Connection
# def find_verified_user
# verified_user = User.find_by(id: cookies.signed['user.id'])
# if verified_user && cookies.signed['user.expires_at'] > Time.now
# verified_user
# else
# reject_unauthorized_connection
# end
# end
# User Logs Off (typically in a session#destroy)
# cookies.signed['user.id'] = nil
# cookies.signed['user.expires_at'] = nil
# messages_controller.rb
class MessagesController < ApplicationController
before_action :authenticate_user!
after_action :verify_authorized
def create
message = current_user.messages.new(params[:message].permit!)
authorize message
message.save
end
end
# message.rb
class Message < ApplicationRecord
belongs_to :user
after_create_commit { MessageBroadcastJob.perform_later(self) }
end
# app/channels/chat_channel.rb
class ChatChannel < ApplicationCable::Channel
def subscribed
stream_from "chat" if current_user.email == 'john.doe@example.com'
end
def unsubscribed
# Any cleanup needed when channel is unsubscribed
end
end