はしばみあきら blog

プログラミングアウトプットするブログ。202010スタート

【RailsでLINEを作る】ルームを作る

※ちょっとエラーが出た部分があったので一部更新(2020/10/20)

お久しぶりの更新です。

Rails の Action cable に大分時間がかかりました...難しい!

1週間かけて rails new して scaffold で実装できたので、いよいよ組み込んでいきたいと思います。

とはいっても見た目は一旦置いといて機能から。まずはチャットを行うルーム機能を作ります。

[参考にしたサイト] [Rails]ダイレクトメッセージ(DM)機能の実装

ユーザー間のチャットルーム機能を作る

まずは簡単にER図を。

f:id:hashibamiakira:20201019122347p:plain

Userはもちろんユーザー、TalkRoomはチャット行う部屋を表します。(もっと簡単な名前にすれば良かったと少し後悔)

中間テーブルは、RoomUserはどのユーザーがどのTalkRoomにいるかを表し、TalkはどのユーザーがどのTalkRoomでチャットを送ったかを表します。

まず、以前作った、友達追加機能(よくあるフォローフォロワー機能)で友達追加します。

f:id:hashibamiakira:20201019123128p:plain

友達追加すると、自身のページで友達一覧が表示されます。その友達をクリックするとトークルームを作るようにします。

f:id:hashibamiakira:20201019123249p:plain f:id:hashibamiakira:20201019123400p:plain

見た目は置いといてこんな感じで。

まずviewのコード。

talk_rooms/index.html.slim(一部抜粋)

          .talk-rooms__list--friends
            span.select-friends-list 友だち
            ul
              - current_user.followings.each do |follower|
                li class="follower" id="#{follower.id}"
                  = link_to user_path(follower.id) do
                    = render partial: 'users/attachment', locals: { user: follower}
                    p = follower.name

自身が追加している友達(フォローユーザー)をeachで回します。 クリックで、その友達のshowへ飛ぶようにします。

続いてコントローラー。ここは参考にしたサイトを思いっきり使わせていただきました。

users_controller.rb

  def show
    @user = User.find(params[:id])
    # ここからルームの分岐
    @current_room = RoomUser.where(user_id: current_user.id)
    @another_room = RoomUser.where(user_id: @user.id)
    unless @user.id == current_user.id
      @current_room.each do |cr|
        @another_room.each do |ar|
          # ルームが存在する時
          if cr.talk_room_id == ar.talk_room_id
            @is_room = true
            @room_id = cr.talk_room_id
          end
        end
      end
      # なければ新規作成
      unless @is_room
        @room = TalkRoom.new
        @room_user = RoomUser.new
      end
    end
  end

自身及び友達が登録されているRoomUserをeachで回し、回している最中に同じTalkRoom.idが存在すれば、それはすでにルームが作成されているのでルームが存在する処理を、なければ新規で作る処理を行います。

続いてshowページのviewです。

users/show.html.slim

p = @user.name
- unless @user.id == current_user.id
  - if @is_room == true
    = link_to "チャット", talk_room_path(@room_id)
  - else
    = form_with model: @room, url: talk_rooms_path, local: true do |f|
      = fields_for @room_user do |ru|
        = ru.hidden_field :user_id, value: @user.id
      = f.submit 'チャット'

もしも友達とのルームがあれば、TlakRoom.showへ遷移し、なければ新規で作る形になります。 新規で作る場合は、submitで talk_rooms_controllerのcreateへ飛びます。

talk_rooms_controller

  def create
    room = TalkRoom.create
    RoomUser.create(user_id: current_user.id, talk_room_id: room.id)
    RoomUser.create(user_id: params[:room_user][:user_id], talk_room_id: room.id)
    # 新規ルーム作成時に、showでparams[:user_id]を使えるようにする
    user = User.find(params[:room_user][:user_id])
    redirect_to talk_room_path(room, user_id: user)
  end

  def show
    @user = User.find(params[:user_id])
    @room = TalkRoom.find(params[:id])
    @talks = @room.talk
  end

まず新規でTalkRoomを作ってしまいます。 新規で作られたTalkRoomに紐づいたRoomUserレコードを2つ作ります。 自身と友達の2つです。

これで同じトークルームに参加しているユーザーが判断できるようになりました。

参考した記事のほぼ丸パクリではありますが、ルーム機能を作ることができました。

いよいよActioncableでチャット機能を作っていきます。

実装がおわたらまたボチボチ更新していきます。