Action Cable in Rail 5
Bài đăng này đã không được cập nhật trong 3 năm
Realtime là một khái niệm được biết đến rộng rãi trong thời đại công nghệ hiện nay, được ứng dụng trong nhiều lĩnh vực từ image processing, IOT,.. và web cũng vậy, nó được sử dụng trong các chức năng tạo thông báo hay khi bạn chat, bạn nhận được những thông tin mới một cách rất nhanh chóng.
HTTP và Websockets
Đối với HTTP, kết nối giữa server và client thì khá là ngắn: đầu tiên client request một resource trên server thì một kết nối đến server sẽ được thiết lập và resource được yêu cầu(có thể là JSON, HTML, XML,…) sẽ được truyền về cho client như là một response. Sau đó, kết nối sẽ bị đóng. Vậy làm thế nào để client nhận biết được data trên server thay đổi, thông thường thì client sẽ request để nhận biết sự thay đổi đó trong một thời gian nhất định. Không giống như HTTP, WebSockets là giao thức cho phép các client và server luông kết nối liên tục với nhâu để truyền data. Các client đăng kí channel với server và khi có thay đổi data thì server sẽ broadcasts data đó đến tất cả các client đã đăng kí channel này. Bằng cách này, cả server và client đều cậ nhật trạng thái mới nhất của data và có thể dễ dàng đồng bộ hóa các xuất hiện các thay đổi. Các controller của Rails được xây dựng nhằm mục đích xử lý các request HTTP và Rails đã đưa ra một giải pháp để handle việc tích hợp xử lý Websockets. Rails 5 sẽ có thêm một thư mục mới bên trong thư mục app gọi là channels. Channels hoạt động như các controller xử lý các request Websockets bằng cách đóng gói các logic thành các đơn vị đặc thù, ví dụ như là chat messages hoặc notifications, các client đăng kí các channels để truyền tải dữ liệu.
- Ưu điểm: -Đối với WebSockets việc cung cấp tới khả năng giao tiếp hai chiều rất mạnh mẽ, có độ trẽ thấp cũng như dẽ dàng xử lý khi phát sinh lỗi -Dung lượng của một kết nối bằng WebSocket sẽ ít hơn rất nhiều so với một HTTP Request.
- Nhược điểm: -Do WebSocket là một tính năng đặc biệt của HTML5 chính vì thế nó vẫn chưa nhận được sự hỗ trợ của tất cả các trình duyệt.
Action Cable
Action Cable là một tính năng tích hợp WebSocket của Rails. Sử dụng Javascript ở phía Client và Ruby ở phía Server. để thực hiện việc real-time. Vậy là mình đã giới thiệu sơ qua về các khái niệm, bây giờ sẽ đến phần sử dụng trong ứng dụng thông báo.
Views
#app/views/notifications/_notification.html.erb
<li>
<%= notification.event %>
<span> <%= notification.created_at.strftime("%d %b. %Y") %></span>
</li>
#app/views/notifications/_notifications.html.erb
<ul class="notificaton">
<div id="notificationContainer">
<div id="notificationTitle">Notifications</div>
<div id="notificationsBody" class="notifications">
<ul id="notificationList">
<%= render notifications %>
</ul>
</div>
<div id="notificationFooter"></div>
</div>
</ul>
2 view này sẽ hiện thị thông báo.
<%= render "notifications", notifications: @notifications %>
gọi render này đến những header hay những view nào bạn muốn hiển thị thông báo.
Notification
Server
tạo một kênh ứng với mục đích sử dụng của mình. Ở đây mình đặt tên là NotificationChannel.
#app/channels/notification_channel.rb
class NotificationChannel < ApplicationCable::Channel
def subscribed
stream_from "notification_channel"
end
def unsubscribed; end
end
Sau khi yêu cầu từ Client đã được chấp nhận, thì Server sẽ thực hiện hàm subscriebed để thực hiện tạo một kênh riêng để trao đối dữ liệu với Client. Hàm unsubscribed để hủy bỏ kênh.
#model/notification.rb
after_create :push_notify
private
def push_notify
ActionCable.server.broadcast "notification_channel",
notification: render_notification self
end
def render_notification notification
ApplicationController.renderer.render partial: "notifications/notification",
locals: {notification: notification}
end
Ở có 2 dữ liệu cần chú ý là tên của kênh và dữ liệu truyền vào kênh. vậy là đã xong việc phần server.
Client
- Consumers sẽ yêu cầu một instance của connection phía client, điều này có thể được thực hiện bằng cách sử dụng Javascript, nó sẽ mặc định được tạo ra bởi Rails.
- Connection consumers: Connect với server dựa vào /cable, Việc kết nối sẽ không được thiết lập cho tới khi bạn có ít nhất một subscription
// /cable.js
// Action Cable provides the framework to deal with WebSockets in Rails.
// You can generate new channels where WebSocket features live using the `rails generate channel` command.
//= require action_cable
//= require_self
//= require_tree ./channels
(function() {
this.App || (this.App = {});
App.cable = ActionCable.createConsumer();
}).call(this);
- Một consumer trở thành một subscriber bằng cách đăng ký vào một channel, Một consumer có thể hành xử như một subscriber để đăng ký nhiều channel. Ví dụ một consumer có thể subscriber tới nhiều phòng chat khác nhau tại cùng một thời điểm
$(document).ready(function() {
(function() {
App.notifications = App.cable.subscriptions.create({
channel: 'NotificationChannel'
},
{
connected: function() {},
disconnected: function() {},
received: function(data) {
current_user = parseInt($('#current-user-id').val());
$('.notificationList').prepend('' + data.notification);
$counter = $('.counter-notification').text();
val = parseInt($counter);
val++;
$('.counter-notification').text(val);
},
});
}).call(this);
});
Tạo kết nối tới kênh mà ta muốn kết nối. Ở đây là NotificationChannel. Dữ liệu nhận về sẽ thông qua biến data ở hàm received.
Settings
Trong routes:
#routes.rb
mount ActionCable.server => "/cable"
Và cho js:
//= require cable
Vậy là đã xong công việc thao tác gửi nhận rồi
Nguồn tham khảo
https://github.com/rails/rails/tree/master/actioncable http://guides.rubyonrails.org/action_cable_overview.html
All rights reserved