Action Cable Rails 5

I. Giới thiệu

  • WebSoket là công nghệ hỗ trợ giao tiếp hai chiều giữa client và server bằng cách sử dụng một TCP socket để tạo một kết nối hiệu quả và ít tốn kém. Mặc dù được thiết kế để chuyên sử dụng cho các ứng dụng web, lập trình viên vẫn có thể đưa chúng vào bất kì loại ứng dụng nào.
  • Với sự hỗ trợ của ActionCable trong Rails 5, chúng ta có thể thực thi WebSockets theo chuẩn thiết kể của Rails.
  • ActionCablelà một bước đi mới quan trọng của Rails, nó cho phép developer chuyển cách request/response sang một cách mới mà ở đó việc kết nối giữa client và Rails server được duy trì. Đây là một kiểu kết nối stateful không giống như HTTP request. chi phí, độ trễ liên quan đến việc đẩy dữ liệu trong thời gian thực được giảm đáng kể so với HTTP.
  • Action Cable có thể chạy độc lập với server, hoặc chúng ta có thể cấu hình cho nó chạy chính process của nó bên trong ứng dụng chính của server.
  • ActionCable cung cấp code để truyền dữ liệu của những nội dung nhất định ( tin nhắn, thông báo ... ) thông qua kênh truyền, tới subscriber ( vùng đang kết nối ). Subscriber được khởi tạo phía client với một đoạn code Javascript, sử dụng Jquery để thêm nội dung vào DOM.
  • ActionCable sử dụng Redis để lưu trữ dữ liệu, đồng bộ nội dung thông qua các instances của ứng dụng

II. Xây dựng 1 ứng dụng đơn giản

  1. Tạo 1 rails app bằng Rails 5
FRAMGIA\[email protected]:~$ rails -v
Rails 5.0.2
FRAMGIA\[email protected]:~$ rails new chat_action_cable
  • Add Gem redis-namespace
gem "redis-namespace"
├── app
    ├── channels
        ├── application_cable
            ├── channel.rb
            └── connection.rb
        └── messages_channel.rb
  • Tạo 1 stream app\channels\mesages_channel.rb
class MessagesChannel < ApplicationCable::Channel
  def subscribed
    stream_from "message_#{params[:chanel_code]}"
  end
end
  • Thiết lậpWebsocket dưới Client
// app/assets/javascripts/cable.js
//= require action_cable
//= require_self
//= require_tree ./channels
(function() {
  this.App || (this.App = {});
  App.cable = ActionCable.createConsumer();
}).call(this);
  • Config socket URL để Client có thể connet tới
// config/environments/staging.rb & config/environments/production.rb
config.action_cable.url = 'wss://your_domain/cable'
config.action_cable.allowed_request_origins = ['https://your_domain, 'https://your_ip']
  • Config Redis
#config/cable.yml
development:
  adapter: async

test:
  adapter: async

staging:
  adapter: redis
  url: <%=ENV['REDIS_URL']%>

production:
  adapter: redis
  url: <%=ENV['REDIS_URL']%>
  • Định nghĩa subscriptions bên Client ``
// app/assets/javascripts/messages.coffee
jQuery(document).on "ready page:load", ->
  if $(".message-box ").length > 0
    chanel_code = $(".message-box").attr("chanel-code")
    App.cable.subscriptions.create {
      channel: "MessagesChannel"
      chanel_code: chanel_code
      },
      connected: ->

      disconnected: ->

      received: (data) ->
        if data["message"]
          $("#fn-message." + data["chanel_code"] + " .md-dm01-detail-box .md-dm02-box").append data["message"]
          $(".md-dm01-box").scrollTop($(".md-dm01-box").prop("scrollHeight"));
        if data["last_message"]
          $("table.last_messages").show();
          $(".md-table01-box-inner .md-detail01-text-wrap").remove();
  • Truyền messages về phía các kênh subscribed
class MessagesController < ApplicationController
  def create
    @message = current_supplier.messages.create! mss_params
    ActionCable.server.broadcast("message_change_code", message:  @message)
    respond_to do |format|
      format.js {render layout: false}
    end
  end
end

Tham khaỏ: https://blog.heroku.com/real_time_rails_implementing_websockets_in_rails_5_with_action_cable