こんにちは。
今回は、RailsでActionCableを使ってSocket通信をする方法について紹介します。
ActionCableとは
ActionCableは、Railsに組み込まれているWebSocketフレームワークです。WebSocketを使うことで、リアルタイムでの双方向通信を実現することができます。
ActionCableを使うことで、チャットアプリやリアルタイムな通知機能などを実装することができます。
今回は、ActionCableを使ってWebhookで特定のユーザーのデータが更新された際に、そのユーザーでログインしている状態の画面があった場合に、リアルタイムでデータを更新する処理を実装してみます。
やっていき
ApplicationCable::Connectionに認証情報を追加する
まず、ApplicationCable::Connection
に認証情報を追加します。
module ApplicationCable
class Connection < ActionCable::Connection::Base
identified_by :current_user
def connect
self.current_user = find_verified_user
end
private
def find_verified_user
User.find(request.session[:user_id])
rescue ActiveRecord::RecordNotFound
reject_unauthorized_connection
end
end
end
request.session[:user_id]
にユーザーIDが入っていることを前提にしています。
deviseを使っている場合は、request.env['warden'].user.id
などで取得することもできます。
チャンネルを作成する
次に、チャンネルを作成します。
class UserChannel < ApplicationCable::Channel
def subscribed
stream_for current_user
end
def unsubscribed
# Any cleanup needed when channel is unsubscribed
end
end
stream_for current_user
で、ユーザーごとのチャンネルを作成しています。
subscribeする
次に、subscribeする処理を実装します。
import "channels"
import { createConsumer } from "@rails/actioncable"
export default createConsumer()
import consumer from "channels/consumer"
consumer.subscriptions.create({ channel: "UserChannel" }, {
connected() {
console.log("Connected to the UserChannel")
},
disconnected() {
console.log("Disconnected from the UserChannel")
},
received(data) {
const userTarget = document.querySelector(`[data-user-id="${data.user.id}"]`)
if (userTarget) {
userTarget.innerHTML = data.user.name
}
}
})
<div data-user-id="<%= @user.id %>">
<%= @user.name %>
</div>
ブロードキャストする
最後に、ブロードキャストする処理を実装します。
class User < ApplicationRecord
after_update_commit { broadcast_update }
def broadcast_update
UserChannel.broadcast_to(self, user: self)
end
end
after_update_commit
で、ユーザーが更新された際にbroadcast_update
メソッドを呼び出しています。
UserChannel.broadcast_to(self, user: self)
で、ユーギザーごとのチャンネルにデータをブロードキャストしています。
これで、特定のユーザーのデータが更新された際に、そのユーザーでログインしている状態の画面があった場合に、リアルタイムでデータを更新する処理が実装できました。
注意点として、この実装の検証のためにbin/rails c
でコンソールを開いて、ユーザーを更新してもリアルタイムでデータが更新されない場合があります。その場合は、config/environments/development.rb
に以下の設定を追加してください。
config.action_cable.disable_request_forgery_protection = true
これで、リアルタイムでデータが更新されるようになります。
今回はこのあたりで。