class ActionCableClient

Constants

VERSION

Attributes

_connected_callback[RW]
_disconnected_callback[RW]
_message_factory[R]
_pinged_callback[RW]
_subscribed[RW]

The queue should store entries in the format:

action, data
_subscribed_callback[RW]
_uri[R]
_websocket_client[R]
message_queue[RW]

The queue should store entries in the format:

action, data

Public Class Methods

new(uri, params = '', connect_on_start = true, headers = {}, tls = {}) click to toggle source

@param [String] uri - e.g.: ws://domain:port @param [String] params - the name of the channel on the Rails server

or params. This gets sent with every request.
 e.g.: RoomChannel

@param [Boolean] connect_on_start - connects on init when true

- otherwise manually call `connect!`

@param [Hash] headers - HTTP headers to use in the handshake @param [Hash] tls - TLS options hash to be passed to EM start_tls

# File lib/action_cable_client.rb, line 39
def initialize(uri, params = '', connect_on_start = true, headers = {}, tls = {})
  @_uri = uri
  @message_queue = []
  @_subscribed = false

  @_message_factory = MessageFactory.new(params)

  connect!(headers, tls) if connect_on_start
end

Public Instance Methods

connect!(headers = {}, tls = {}) click to toggle source
# File lib/action_cable_client.rb, line 49
def connect!(headers = {}, tls = {})
  # Quick Reference for WebSocket::EM::Client's api
  # - onopen - called after successfully connecting
  # - onclose - called after closing connection
  # - onmessage - called when client recives a message. on `message do |msg, type (text or binary)|``
  #             - also called when a ping is received
  # - onerror - called when client encounters an error
  # - onping - called when client receives a ping from the server
  # - onpong - called when client receives a pong from the server
  # - send - sends a message to the server (and also disables any metaprogramming shenanigans :-/)
  # - close - closes the connection and optionally sends close frame to server. `close(code, data)`
  # - ping - sends a ping
  # - pong - sends a pong
  @_websocket_client = WebSocket::EventMachine::Client.connect(uri: @_uri, headers: headers, tls: tls)

  @_websocket_client.onclose do
    self._subscribed = false
    _disconnected_callback&.call
  end
end
connected() { |json| ... } click to toggle source

callback when the client connects to the server

@example

client = ActionCableClient.new(uri, 'RoomChannel')
client.connected do
  # do things after the client is connected to the server
end
# File lib/action_cable_client.rb, line 106
def connected
  self._connected_callback = proc do |json|
    yield(json)
  end
end
disconnected() { || ... } click to toggle source

callback when the server disconnects from the client.

@example

client = ActionCableClient.new(uri, 'RoomChannel')
client.connected {}
client.disconnected do
  # cleanup after the server disconnects from the client
end
# File lib/action_cable_client.rb, line 142
def disconnected
  self._disconnected_callback = proc do
    yield
  end
end
perform(action, data) click to toggle source

@param [String] action - how the message is being sent @param [Hash] data - the message to be sent to the channel

# File lib/action_cable_client.rb, line 78
def perform(action, data)
  dispatch_message(action, data)
end
pinged(&block) click to toggle source
# File lib/action_cable_client.rb, line 148
def pinged(&block)
  self._pinged_callback = block
end
received() { |json| ... } click to toggle source

callback for received messages as well as what triggers depleting the message queue

@example

client = ActionCableClient.new(uri, 'RoomChannel')
client.received do |message|
  # the received message will be JSON
  puts message
end
# File lib/action_cable_client.rb, line 91
def received
  _websocket_client.onmessage do |message, _type|
    handle_received_message(message) do |json|
      yield(json)
    end
  end
end
reconnect!() click to toggle source
# File lib/action_cable_client.rb, line 70
def reconnect!
  uri = URI(@_uri)
  EventMachine.reconnect uri.host, uri.port, @_websocket_client
  @_websocket_client.post_init
end
subscribed(&block) click to toggle source

callback when the client receives a confirm_subscription message from the action_cable server. This is only called once, and signifies that you can now send messages on the channel

@param [Proc] block - code to run after subscribing to the channel is confirmed

@example

client = ActionCableClient.new(uri, 'RoomChannel')
client.connected {}
client.subscribed do
  # do things after successful subscription confirmation
end
# File lib/action_cable_client.rb, line 125
def subscribed(&block)
  self._subscribed_callback = block
end
subscribed?() click to toggle source

@return [Boolean] is the client subscribed to the channel?

# File lib/action_cable_client.rb, line 130
def subscribed?
  _subscribed
end

Private Instance Methods

check_for_subscribe_confirmation(message) click to toggle source

{“identifier” => “_ping”,“type” => “confirm_subscription”}

# File lib/action_cable_client.rb, line 175
def check_for_subscribe_confirmation(message)
  message_type = message[Message::TYPE_KEY]
  return unless  Message::TYPE_CONFIRM_SUBSCRIPTION == message_type

  self._subscribed = true
  _subscribed_callback&.call
end
dispatch_message(action, data) click to toggle source
# File lib/action_cable_client.rb, line 201
def dispatch_message(action, data)
  # can't send messages if we aren't subscribed
  return unless subscribed?

  msg = _message_factory.create(Commands::MESSAGE, action, data)
  json = msg.to_json
  send_msg(json)
end
handle_received_message(message) { |json| ... } click to toggle source

@param [String] message - the websockt message object

# File lib/action_cable_client.rb, line 155
def handle_received_message(message)
  return if message.empty?

  json = JSON.parse(message)

  if is_ping?(json)
    _pinged_callback&.call(json)
  elsif is_welcome?(json)
    subscribe
    _connected_callback&.call(json)
  elsif !subscribed?
    check_for_subscribe_confirmation(json)
  else
    # TODO: do we want to yield any additional things?
    #       maybe just make it extensible?
    yield(json)
  end
end
is_ping?(message) click to toggle source

{“identifier” => “_ping”,“message” => 1460201942} {“identifier” => “_ping”,“type” => “confirm_subscription”}

# File lib/action_cable_client.rb, line 185
def is_ping?(message)
  message_identifier = message[Message::TYPE_KEY]
  Message::IDENTIFIER_PING == message_identifier
end
is_welcome?(message) click to toggle source

{“type” => “welcome”}

# File lib/action_cable_client.rb, line 191
def is_welcome?(message)
  message_identifier = message[Message::TYPE_KEY]
  Message::IDENTIFIER_WELCOME == message_identifier
end
subscribe() click to toggle source
# File lib/action_cable_client.rb, line 196
def subscribe
  msg = _message_factory.create(Commands::SUBSCRIBE)
  send_msg(msg.to_json)
end