Action Cable Overview — Ruby on Rails Guides

Full code:
class GuruChannel < ApplicationCable::Channel

  STREAM_PREFIX = 'GuruChannel'

  def unsubscribed
    # Any cleanup needed when channel is unsubscribed
  end

  def subscribed
    stream_from(stream)
    transmit(stream_state)
  end

  def receive(data)
    message = to_json(data).fetch(:message)
    ActionCable.server.broadcast(stream, message)
  end

  private

  def stream
    "#{STREAM_PREFIX}_#{job_slug}"
  end

  def job_slug
    params.fetch(:job_slug)
  end

  def to_json(data)
    JSON.parse(data.to_json, symbolize_names:true)
  end

  def stream_state
    Redis.current.get(stream)
  end
end​

Using transmit to send message to only the current connection.
def subscribed
    stream_from(stream)
    transmit(stream_state)
end​

Using broadcast to broadcast message to all connections. Message won't be sent directly from client to client, but from client to server. Server broadcast message to clients then.

def receive(data)
    message = to_json(data).fetch(:message)
    ActionCable.server.broadcast(stream, message)
end

Server will call receive if client send. Below line just sends from Server to all clients.
ActionCable.server.broadcast(stream, message)​


Note that we must configure redis same as the server using Socket /cable if using multiple servers.

development:
  adapter: redis
  url: redis://localhost:6379

test:
  adapter: async

staging:
  adapter: redis
  url: redis://willnguyen.com:6379

production:
  adapter: redis
  url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>


For example. We have the second one for background job. If we use ActionCable in background job, we have to point to the Redis that the first server uses - The same Redis to let two servers see the same number of connections.

server 'xxx.xxx.xxx.xx', user: 'truong', roles: %w{app db web}, primary: true
server 'yy.yyy.yyy.yyy', user: 'truong', roles: %w{app worker whenever}