RailsでリアルタイムランダムマッチングWebアプリ

1pt   2018-11-08 13:50
IT技術情報局

はじめに

Railsを勉強する題材として、リアルタイムチャットを作りました。
TALKROOM
ActionCableを利用した通信、複数ルームの作成はネット上の情報をそのまま参考しましたが、ランダムマッチング機能については自分で考えてみたので、シェアしようと思いました。
プログラミング自体初心者なので、もっとこう書いたほうが良いなどの意見がありましたら教えていただけると嬉しいです。

コードは全てGitHubにアップしております。
https://github.com/EMmaxcoffee/talkroom_app

バージョン

Ruby 2.5.1
Rails 5.2.1

リアルタイムチャット

こちらの記事をそのまま参考にしました。
Rails 5 + ActionCableで作る!シンプルなチャットアプリ(DHH氏のデモ動画より)

こちらの記事の通りやれば、ひとつのルームに対するリアルタイムチャットが作れます。

複数ルーム作成

こちらの記事を参考にしました。
Rails 5 Action Cable メッセージとルームを紐付ける。

TALKROOMには通常のチャットルームとランダムマッチルームがあります。
通常のチャットルームはほぼ上記の2つの記事で完成します。

ランダムマッチング ランダムマッチの仕組み

ルームには”user1_id”,”user2_id”という2つのカラムをつけました。
ルームに入室すればそのルームのuser1またはuser2に入室したユーザーのidを代入します。
indexアクションでuser1またはuser2が空(つまり満室ではないルーム)の部屋を探してあればそこに移動、なければ新しいルームを作る処理にしました。
ルームに入室したら「◯◯さんが入室しました」というメッセージが表示、退出すれば「◯◯さんが退出しました」というメッセージを表示させるとともにuser1 or user2 がnilになり、またルームにいるのは1人でその人は待機中というような流れになります。
ちなみにルームに1人だけ入っていて、その人も抜けたらuser1とuser2両方がnilになるので、そのときはルーム自体を削除する処理を加えました。

下記コードは入室時と退出時の処理を書いたコードです。

chat_room_channel.rb class ChatRoomChannel < ApplicationCable::Channel def subscribed if params['chat_room_id'].present? stream_from "chat_room_channel_#{params['chat_room_id']}" current_chat_room = ChatRoom.find(params['chat_room_id']) if current_chat_room.user1_id.nil? current_chat_room.user1_id = current_user.id current_chat_room.save elsif current_chat_room.user2_id.nil? current_chat_room.user2_id = current_user.id current_chat_room.save else redirect_to rooms_path end greet end end def unsubscribed current_chat_room = ChatRoom.find(params['chat_room_id']) if current_chat_room.user1_id == current_user.id current_chat_room.user1_id = nil elsif current_chat_room.user2_id == current_user.id current_chat_room.user2_id = nil end current_chat_room.save if current_chat_room.user1_id == nil && current_chat_room.user2_id == nil current_chat_room.destroy end farewell_greet end def speak(data) Chat.create(content: data['chat'], user_id: current_user.id, user_name: current_user.name, chat_room: ChatRoom.find(params['chat_room_id'])) user_update end private def user_update user = current_user user.touch user.save end def greet Chat.create(content: "#{current_user.name}が入室しました。", user_id: current_user.id, user_name: current_user.name, chat_room: ChatRoom.find(params['chat_room_id'])) end def farewell_greet Chat.create(content: "#{current_user.name}が退出しました。", user_id: current_user.id, user_name: current_user.name, chat_room: ChatRoom.find(params['chat_room_id'])) end end

下記はControllerの処理です。
user1またはuser2が空のルームを探してUserを移動させています。

chat_rooms_controller.rb class ChatRoomsController < ApplicationController before_action :logged_in_user def show @chat_room = ChatRoom.find(params[:id]) @chats = @chat_room.chats end def index @free_user1_chat_room = ChatRoom.where(user1_id: nil).where.not(user2_id: nil) @free_user2_chat_room = ChatRoom.where.not(user1_id: nil).where(user2_id: nil) if @free_user1_chat_room.present? redirect_to controller: "chat_rooms", action: "show", id: @free_user1_chat_room.first.id elsif @free_user2_chat_room.present? redirect_to controller: "chat_rooms", action: "show", id: @free_user2_chat_room.first.id else @new_chat_room = ChatRoom.create redirect_to controller: "chat_rooms", action: "show", id: @new_chat_room.id end end end 作ってみて

リアルタイムと複数ルームは非常に参考になる記事があったので、すんなり実装できました。ランダムマッチに関する記事は検索方法が悪いのか、ほとんど見つけることができず、自分で考えて実装することにしました。
はじめはユーザーがルームに入ったのと出たのをどうやって判別するのかがわからずずっと悩んでました。
ActionCableの記事やサイトで
subscribedとunsubscribedを使っているのあまり見たことないから、これを利用すれば良いということに気づきませんでした。

かなり初歩的なところだからってことであまり触れないんですかね。

Source: rails tag

   ITアンテナトップページへ
情報処理/ITの話題が沢山。