複数のプライベートルームとグループチャットオプションでRails
このポストは、チュートリアルではないことに注意してください
(この短いポストはこのフロントエンドコンポーネントをビルドする方法を示しません)
つの素晴らしい機能が付属して Rails 5 APIバックエンドとreactjsフロントエンド 複数の個室 部屋のユーザーの任意の正の数 チャットシステムマイフレンドTim Chang 私は構築しました. 複数のプライベートチャットルーム 複数のチャットルーム 各ユーザーのオンライン/オフラインのステータス リアルタイム“タイピング…”ステータス リアルタイム読み取り領収書 この短いポストでは、1 . 1と1 . 2の基本を示します.あなたが私にあなたがサイ3 , 5 , 4と5 , 5を造る方法を示すことを望むならば、下記のコメントを残してください.私はRails 5をバックエンドAPIとreactjsライブラリをフロントエンドで使用しています.
バックエンド
作成時には、柵はすべてのリアルタイムマジックが発生するチャネルフォルダとファイルを生成します.
まず、接続中のRailsサーバへのWebSocket接続要求を認証しましょう.rb
データ構造
アイデアは非常に基本的です:複数のメッセージを持っているチャットルームは、各メッセージは、コンテンツと送信者があります.メッセージに「受信機」がないことに注意してください.これは、部屋のどのように多くの参加者に関係なく、送信者からのすべてのメッセージが部屋に表示されなくなりますので、メッセージの受信機を気にする必要はありませんので、部屋の任意の数のユーザーを持つことができます.したがって、これは私が使用するデータ構造です: 多くのメッセージ、ユーザー、IDを持つ メッセージ:所有者は会話に、送付者を持って、テキスト内容を持っています 送信者:ユーザ その結果、3つのモデルを作成しました.
クライアントが接続(購読)またはメッセージ(放送)を放送すると、バックエンドはアクションと反応します.インサイドフォルダ
このコールバックは、メッセージが生成され、DBにコミットされた後にのみ呼び出されます.私はスケールするためにこのアクションを処理するためにバックグラウンドジョブを使用しています.あなたがメッセージを送信する何千ものクライアントがあると想像してください.バックグラウンドジョブの使用はここでの要件です.
あなたは/WebSocketルートを追加する必要があります
クライアントライブラリ
あなたのプロジェクトの詳細に応じて、このライブラリのこのコードの概念を理解し、必要に応じて変更する必要がありますのでご注意ください.
まず、インストール
クリエイトア
彼らは:受信と話す!
サーバからクライアントにメッセージ放送があるとき、受け取られたメソッドは呼ばれます、反対側では、クライアントがメッセージをサーバーに放送するとき、話すことは呼ばれます.
Voila!それです.繰り返しますが、これは各プロジェクトが異なっているので、チュートリアルのボックスの種類から実行する準備ができてされていませんが、それはあなたがどのように複数のプライベートチャットルームと部屋ごとに複数のユーザーとチャットシステムを構築するためのアイデアを与えることを願っています.質問があればコメント欄でお知らせください.
そして、これはあなたのプロジェクトに役立つ見つける場合は、愛のボタンを押すことを忘れないでください!
Rails 5
ActionCable
and ReactJS
/ Javascript
カスタムライブラリビル.(この短いポストはこのフロントエンドコンポーネントをビルドする方法を示しません)
つの素晴らしい機能が付属して
Rails 5
is ActionCable
. With ActionCable
, あなたはWebSocket経由で考えることができるすべてのリアルタイム機能を構築することができます.一方、チャットシステムを構築するために苦労して、私はRails 5
ActionCable
しかし、彼らはまた、任意の実際の生活のチャットアプリケーションのコンセプトを適用するために簡単です.私は、このようなチャットシステムを構築する方法を示しています.バックエンド
作成時には、柵はすべてのリアルタイムマジックが発生するチャネルフォルダとファイルを生成します.
app/channels/application_cable/channel.rb
app/channels/application_cable/connection.rb
認証まず、接続中のRailsサーバへのWebSocket接続要求を認証しましょう.rb
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
# or however you want to verify the user on your system
access_token = request.params[:'access-token']
client_id = request.params[:client]
verified_user = User.find_by(email: client_id)
if verified_user && verified_user.valid_token?(access_token, client_id)
verified_user
else
reject_unauthorized_connection
end
end
end
end
プロジェクトで使用する認証gemまたはサービスによって異なります.find_verified_user
メソッドを必要に応じて変更する必要があります.という方法があるvalid_token?
確認するaccess-token
and client_id
WebSocketリクエストで渡します.要求が認証されないならば、それは拒絶されます.データ構造
アイデアは非常に基本的です:複数のメッセージを持っているチャットルームは、各メッセージは、コンテンツと送信者があります.メッセージに「受信機」がないことに注意してください.これは、部屋のどのように多くの参加者に関係なく、送信者からのすべてのメッセージが部屋に表示されなくなりますので、メッセージの受信機を気にする必要はありませんので、部屋の任意の数のユーザーを持つことができます.したがって、これは私が使用するデータ構造です:
# message.rb
class Message < ApplicationRecord
belongs_to :conversation
belongs_to :sender, class_name: :User, foreign_key: 'sender_id'
validates_presence_of :content
after_create_commit { MessageBroadcastJob.perform_later(self) }
end
# conversation.rb
class Conversation < ApplicationRecord
has_many :messages, dependent: :destroy
has_and_belongs_to_many :users
end
# user.rb
class User < ApplicationRecord
has_and_belongs_to_many :conversations, dependent: :destroy
end
アクショントリガークライアントが接続(購読)またはメッセージ(放送)を放送すると、バックエンドはアクションと反応します.インサイドフォルダ
app/channels
, ファイルを作成しますroom_channel.rb
.# room_channel.rb
class RoomChannel < ApplicationCable::Channel
# calls when a client connects to the server
def subscribed
if params[:room_id].present?
# creates a private chat room with a unique name
stream_from("ChatRoom-#{(params[:room_id])}")
end
end
# calls when a client broadcasts data
def speak(data)
sender = get_sender(data)
room_id = data['room_id']
message = data['message']
raise 'No room_id!' if room_id.blank?
convo = get_convo(room_id) # A conversation is a room
raise 'No conversation found!' if convo.blank?
raise 'No message!' if message.blank?
# adds the message sender to the conversation if not already included
convo.users << sender unless convo.users.include?(sender)
# saves the message and its data to the DB
# Note: this does not broadcast to the clients yet!
Message.create!(
conversation: convo,
sender: sender,
content: message
)
end
# Helpers
def get_convo(room_code)
Conversation.find_by(room_code: room_code)
end
def get_sender
User.find_by(guid: id)
end
end
コメントの中で、クライアントが「話す」の後、放送はまだ起きていません新しいメッセージだけがその内容とデータで作成されます.アクションの連鎖は、メッセージがDBに保存された後に発生します.メッセージモデルを見てみましょう.after_create_commit { MessageBroadcastJob.perform_later(self) }
スケーラビリティこのコールバックは、メッセージが生成され、DBにコミットされた後にのみ呼び出されます.私はスケールするためにこのアクションを処理するためにバックグラウンドジョブを使用しています.あなたがメッセージを送信する何千ものクライアントがあると想像してください.バックグラウンドジョブの使用はここでの要件です.
# message_broadcast_job.rb
class MessageBroadcastJob < ApplicationJob
queue_as :default
def perform(message)
payload = {
room_id: message.conversation.id,
content: message.content,
sender: message.sender,
participants: message.conversation.users.collect(&:id)
}
ActionCable.server.broadcast(build_room_id(message.conversation.id), payload)
end
def build_room_id(id)
"ChatRoom-#{id}"
end
end
放送が起こるときは、ここにあります.ActionCable
は、ペイロードを指定された部屋に提供されたペイロードで放送します.ActionCable.server.broadcast(room_name, payload)
ケーブルルートあなたは/WebSocketルートを追加する必要があります
routes.rb
あなたのクライアントがこの終点を放送して、メッセージを受け取ることができるように.mount ActionCable.server => '/cable'
そして、それはバックエンド側のためです!reactjsフロントエンドライブラリを見てみましょう.クライアントライブラリ
あなたのプロジェクトの詳細に応じて、このライブラリのこのコードの概念を理解し、必要に応じて変更する必要がありますのでご注意ください.
まず、インストール
ActionCableJS
経由npm
.クリエイトア
ChatConnection.js
あなたのサービスの1つとしてファイルReactJs
アプリ.// ChatConnection.js
import ActionCable from 'actioncable'
import {
V2_API_BASE_URL,
ACCESS_TOKEN_NAME,
CLIENT_NAME,
UID_NAME
} from '../../globals.js'
function ChatConnection(senderId, callback) {
let access_token = localStorage.getItem(ACCESS_TOKEN_NAME)
let client = localStorage.getItem(CLIENT_NAME)
var wsUrl = 'ws://' + V2_API_BASE_URL + '/cable'
wsUrl += '?access-token=' + access_token + '&client=' + client
this.senderId = senderId
this.callback = callback
this.connection = ActionCable.createConsumer(wsUrl)
this.roomConnections = []
}
ChatConnection.prototype.talk = function(message, roomId) {
let roomConnObj = this.roomConnections.find(conn => conn.roomId == roomId)
if (roomConnObj) {
roomConnObj.conn.speak(message)
} else {
console.log('Error: Cannot find room connection')
}
}
ChatConnection.prototype.openNewRoom = function(roomId) {
if (roomId !== undefined) {
this.roomConnections.push({roomId: roomId, conn: this.createRoomConnection(roomId)})
}
}
ChatConnection.prototype.disconnect = function() {
this.roomConnections.forEach(c => c.conn.consumer.connection.close())
}
ChatConnection.prototype.createRoomConnection = function(room_code) {
var scope = this
return this.connection.subscriptions.create({channel: 'RoomChannel', room_id: room_code, sender: scope.senderId}, {
connected: function() {
console.log('connected to RoomChannel. Room code: ' + room_code + '.')
},
disconnected: function() {},
received: function(data) {
if (data.participants.indexOf(scope.senderId) != -1) {
return scope.callback(data)
}
},
speak: function(message) {
return this.perform('speak', {
room_id: room_code,
message: message,
sender: scope.senderId
})
}
})
}
export default ChatConnection
だからここにフックがありますcreateRoomConnection
, クライアントは(接続する)と接続しようとしますRoomChannel
我々はバックエンドでは、一度接続されて(予約)、それは部屋の名前からストリームされます作成されたChatRoom-id
見るroom_channel.rb
上に再び.)一度接続されている、それは頻繁に呼ばれる2つの方法があり、どの1つを推測することができますか?彼らは:受信と話す!
サーバからクライアントにメッセージ放送があるとき、受け取られたメソッドは呼ばれます、反対側では、クライアントがメッセージをサーバーに放送するとき、話すことは呼ばれます.
Voila!それです.繰り返しますが、これは各プロジェクトが異なっているので、チュートリアルのボックスの種類から実行する準備ができてされていませんが、それはあなたがどのように複数のプライベートチャットルームと部屋ごとに複数のユーザーとチャットシステムを構築するためのアイデアを与えることを願っています.質問があればコメント欄でお知らせください.
そして、これはあなたのプロジェクトに役立つ見つける場合は、愛のボタンを押すことを忘れないでください!
Reference
この問題について(複数のプライベートルームとグループチャットオプションでRails), 我々は、より多くの情報をここで見つけました https://dev.to/mreigen/build-a-chat-system-using-rails-5-api-action-cable-and-reactjs-with-multiple-private-rooms-and-group-chat-option-o8kテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol