ActionCable in Rails5

Howto
Why
Notices

Howto

  • Turn on Cable Route
  • Design & Create new Channel
  • Connect Javascript Code to Channel
# in /config/routes.rb
mount ActionCable.server => '/cable'


# in /app/assets/javascripts/cable.coffee
@App ||= {}
App.cable = ActionCable.createConsumer()


Turn on Action Cable


# Generated by `rails g channel hall talk`

# in /app/channels/hall_channel.rb

class HallChannel < ApplicationCable::Channel
  def subscribed
    stream_from "hall_channel"
  end

  def talk(what)
    ActionCable.server.broadcast 'hall_channel', what
  end

  def unsubscribed
    # Any cleanup needed when channel is unsubscribed
  end
end

Design & Create new Channel



# in /app/assets/javascripts/channels/hall.coffee

App.hall = App.cable.subscriptions.create "HallChannel",
  connected: ->
    # Called when the subscription is ready for use on the server

  disconnected: ->
    # Called when the subscription has been terminated by the server

  received: (data) ->
    # Define our action here
    $('.container').append(data['what'] + "\n")

Design & Create new Channel(2)


# Generated by `rails g controller hall index`

# in /app/assets/javascripts/hall.coffee

$(document).on 'ready', ->
  $('#talk').on 'keyup', (event)->
    if(event.keyCode == 13)
      App.hall.perform('talk', what: @value)
      @value = ''

Connect Javascript Code to Channel


# Generated by `rails g controller hall index`

# in /app/views/hall/index.html.erb

<h1>Welcome to Hall</h1>
<p class='container'></p>
<p class='input'>
  <input id='talk' type='text' />
</p>

Connect Javascript Code to Channel(2)


// Generated by `rails g controller hall index`

// in /app/assets/stylesheets/hall.scss

.container {
  border: 1px solid #ccc;
  padding: 30px;
  min-height: 500px;
  white-space: pre;
}

.input input {
  width: 500px;
}

Connect Javascript Code to Channel(3)

Test it

  • open http://localhost:3000 in one browser
  • open http://localhost:3000 in another browser
  • input some text in text field below and press enter to send
  • we should see text received and showed above

Full Example

# Simple Example Enough

https://github.com/windy/rails5chatroom_example


# Ruby China Exmaple

https://github.com/ruby-china/ruby-china/commit/7193062fa3b8538af504ba470a23442dbdc01896

Howto
Why
Notices

  • ActionCable Worker Thread Pool
  • ActionCable SubPub System IO Pool
  • ActionCable TimerTask Pool

Thread Pool Info

Simple use cookie for authentication

  • use rack hijack protocol
  • request.cookies to get cookies
  • just use signed cookies
# get cookie 

cookies.signed[:cookie_name]

Core Implement

ActionCable::Server

A global singleton instance, we can use it for broatcasting message, close connection or channel

ActionCable::Connection

Every Connection Instance hold a websocket, Channel will receive specified message routed by connection & subscriptions

ActionCable::Subscriptions

Subscriptions are held by ActionCable::Connections to recieve sub/pub data and create Channel Object for that.

action_cable.js

A client action cable protocol implement, core funtion is:

 

  • ActionCable.createConsumer
  • ActionCable.Subscriptions.create
  • ActionCable.Subscriptions#send
  • ActionCable.Subscriptions#perform
# a really simple action cable client written by ruby
https://github.com/NullVoxPopuli/action_cable_client

Rack hi.jack technology

Rack hi.jack can let HTTP(s) handler Upgrade to Other Protocol for example Websocket

see an example: hijack example

more info: hijack in rack

Howto
Why
Notices

Conclusion

  • Simple to use
  • Powerful than SocketIO(nodejs)
  • Take care with concurrency program

Standalone vs Multi Process

  • Redis
  • Remote Connection communication

Channel vs Controller

  • non-autoreload
  • non-restful
  • access cookie but not session
  • use signed cookie not normal cookie
  • use http://localhost:3000 not http://127.0.0.1:3000(why?)

Deployment

  • Support puma, unicorn, passenger but not webrick
  • Multi-threaded besides Rails Server
  • Open socket upper limit :   ulimit -Sn
  • Update config.action_cable.allowed_request_origins

Refercence

  • action cable source code & byebug tool
  • http://old.blog.phusion.nl/2013/01/23/the-new-rack-socket-hijacking-api/
  • https://github.com/rails/rails/tree/master/actioncable
  • https://www.amberbit.com/blog/2015/4/22/why-rails-5-turbolinks-3-action-cable-matter-and-why-dhh-was-right-all-along/

Rails philosophy

Make making web app simple enough

Thx & QA

ActionCable in Rails5

By Li Yafei

ActionCable in Rails5

  • 4,224