Online/offline appearance realtime với Actioncable trong Rails 5
Actioncable là tính năng mới của Rails 5 nhờ sử dụng websocket để tạo realtime application một cách đễ dàng và nhanh chống, cho phép server và client tương tác với nhau realtime. Hôm này mình sẽ đưa ra một ví dụ về cách sử dụng actioncable để tạo Online/offline appearance cho người dùng hệ ...
Actioncable là tính năng mới của Rails 5 nhờ sử dụng websocket để tạo realtime application một cách đễ dàng và nhanh chống, cho phép server và client tương tác với nhau realtime. Hôm này mình sẽ đưa ra một ví dụ về cách sử dụng actioncable để tạo Online/offline appearance cho người dùng hệ thống. Về phần đầu tiên để config, tạo channel hoặc cách làm việc của actioncable thế nào mình sẽ không nói ở đây nữa. Nếu bạn chưa làm quên với nó, có thể tham khảo một số tài liệu sau: https://github.com/rails/rails/tree/master/actioncable https://blog.heroku.com/real_time_rails_implementing_websockets_in_rails_5_with_action_cable
- Tạo migration them column online:boolean mới vào bảng user (hoặc bảng khác tùy thuộc vào project của bạn). Trường này dùng để lưu appearance của user để biết là đang online hay không.
class AddOnlineToUser < ActiveRecord::Migration[5.0] def change add_column :users, :online, :boolean, default: :false end end
chạy migrate:
rake db:migrate
- Tạo list user cùng với status online/offline:
# app/controllers/rooms_controller.rb def show @users = User.page(params[:page]).per 10 end
<ul id="users-list"> <% @users.each do |member| %> <li> <%= member.name %> <% if member.online %> <%= image_tag "green_dot.png", id: "#{member.user_id}-status", class: "active" %> <% else %> <%= image_tag "green_dot.png", id: "#{member.user_id}-status", class: "inactive" %> <% end %> </li> <% end %> </ul>
Styles css:
/* app/assets/stylesheets/main.css */ .active { display: ; } .inactive { display: none; }
- Tạo appearance channel: Khi user join vào hệ thống (subscribe) thì mình sẽ update online: true. Khi user ra khỏi hệ thống (unsubscribe) thì mình sẽ update online: false.
rails g channel appearance
Channel sẽ có như sau:
#app/channels/appearance_channel.rb class AppearanceChannel < ApplicationCable::Channel def subscribed member = User.where(user_id: current_user.id).first return unless member member.update_attributes(online: true) stream_from "appearance_user" end def unsubscribed member = User.where(user_id: current_user.id).first return unless member member.update_attributes(online: false) end end
- Tạo job để publish data: sau khi user thay đổi status online thành true/false, chúng ta sẽ publish data tới client để cập nhật lại hình ảnh active (green dot) hoặc không active (không hiện green dot).
rails g job AppearanceBroadcast
#app/jobs/appearance_broadcast_job.rb class AppearanceBroadcastJob < ApplicationJob queue_as :default def perform(user) ActionCable.server.broadcast "appearance_user", render_json(user) end private def render_json(user) ApplicationController.renderer.render(json: user) end end
# app/models/user.rb add this right under the validations after_update_commit {AppearanceBroadcastJob.perform_later self}
Sau khi server đã publish data, bên client sẽ nhận được đã data đó và phải xử lý cập nhật lại hình ảnh active (green dot) hoặc không active (không hiện green dot).
// app/assets/javascripts/channels/appearance.js App.appearance = App.cable.subscriptions.create({ channel:'AppearanceChannel' }, { received: function(data) { var user = JSON.parse(data) if (user.online === true){ $(userImgIdConstructor(user)).attr('class', 'active'); }; if (user.online === false){ $(userImgIdConstructor(user)).attr('class', 'inactive'); }; } }); var userImgIdConstructor = function(user){ return "#" + user.user_id + "-status"; }
Done! Bây giờ chúng ta đã làm xong về việc tạo online/offline status cho hệ thông của mình. Bạn thấy rằng nhờ sử dụng actioncable thì việc tạo realtime application không phải là vấn đề khó khăn nữa.