Setup

Trước mắt để dùng ta cần config 1 số chỗ

Gemfile

gem 'redis'

config/cable.yml

default: &default
adapter: redis
url: redis://localhost:6379/1

development:
  <<: *default

test:
  <<: *default

Trong file routes thêm

mount ActionCable.server => "/cable"

Ở thư mục javascripts: tạo 1 file cable.js

//= require action_cable
//= require_self
//= require_tree ./channels

(function() {
  this.App || (this.App = {});

  App.cable = ActionCable.createConsumer();

}).call(this);

Nhớ restart server

Cách nó hoạt động

Phía server ta tạo meos_channel.rb để định nghĩa channel user sẽ connect đến tại app/channels/meos_channel.rb

class MeosChannel < ApplicationCable::Channel
  def subscribed
    stream_from "meo_meo_channel"
    # đăng kí nhận tất cả tin nhắn trên channel backs
  end

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

subscribed là method mặc định cho phép chúng ta đăng kí kênh channel mà chúng ta muốn lắng nghe. Khi client connect channel nó sẽ sử dụng thằng channel chúng ta định nghĩa ở đây để lắng nghe những thay đổi

Phía client javascript:

App.notifications = App.cable.subscriptions.create({
      channel: 'MeosChannel'
    },
    {
      connected: function() {
        console.log("connected channel");
      },
      disconnected: function() {
        console.log("disconnected channel");
      },
      received: function(data) {
        console.log("received data")
        console.log(data);
      }
    });
  }).call(this);

connected: Called when the subscription is ready for use on the server

disconnected: Called when the subscription has been terminated by the server

received: Called when there’s incoming data on the websocket for this channel

Khi tải trang bất kì ta xem log server sẽ thấy user đang kết nối đến kênh meo_meo_channel, phía client js sẽ nhận bất cứ data nào gửi đến meo_meo_channel

MeosChannel is transmitting the subscription confirmation
MeosChannel is streaming from meo_meo_channel

Ta có thể thử test server gửi message về cho client bằng rails console:

Loading development environment (Rails 5.2.2.1)
[1] pry(main)> ActionCable.server.broadcast "meo_meo_channel", message: "haha"
[ActionCable] Broadcasting to meo_meo_channel: {:message=>"haha"}
=> 1
[2] pry(main)> 

Nếu kết quả trả về là 1 tức là đã gửi tin nhắn đến meo_meo_channel thành công. meo_meo_channel sẽ lập tức gửi data về dưới client.

Nhìn log trên server sẽ thấy nó đã gửi {message: “haha”} đến meo_meo_channel

MeosChannel transmitting {"message"=>"haha"} (via streamed from meo_meo_channel)

Nếu kết quả = 0 tức là gửi thất bại, cái này nguyên nhân có thể là do ta truyền sai tên kênh channel mà user đang kết nối đến hoặc do chưa đổi config cable.yml

default: &default
adapter: redis
url: redis://localhost:6379/1

development:
  <<: *default

test:
  <<: *default

Dưới client check trên console của trình duyệt sẽ nhận được data mà ta truyền từ server (do mình để console.log nó sẽ in ra kết quả mình trả về)

received data
{message: "haha"}

ở javascript

received: function(data) {
        console.log("received data")
        console.log(data);
}

ta xử lý thêm đoạn received, khi nhận dữ liệu từ server về ta append data zô html ví dụ ntn

$("p").append("data.message");

thì sẽ nhìn đoạn message dc hiển thị ra

=> Chung quy lại ý tưởng là xử lý server khi dữ liệu thay đổi ntn ta sẽ bắn message về cho channel, việc của client là dùng js để hiển thị nó lên

Vậy là qua ví dụ nhỏ trên ta đã mường tượng sơ qua về cách server truyền dữ liệu đến client ntn để nó realtime

Sau khi hiểu sơ cua về nó ta ứng dụng nó gửi notification nhé Về ý tưởng có thể tham khảo tại đây

https://gist.github.com/excid3/4ca7cbead79f06365424b98fa7f8ecf6