学生向けプログラミング入門 | 無料

学生向けにプログラミングを無料で解説。Java、C++、Ruby、PHP、データベース、Ruby on Rails, Python, Django

Rails6.0 | 民泊予約サイトの構築 | 49 | メッセージと会話 | リアルタイムメッセージ

[48]メッセージと会話 | 会話表示<< [ホームに戻る] >> [50]通知


メッセージをリアルタイムで送りあうことができるようにします。


コマンド
rails g channel Message


ルートの設定をします。


記述追加 config\routes.rb
6行目に「mount ActionCable.server => '/cable'」の記述を追加しています。

Rails.application.routes.draw do

  # ルートを app\views\pages\home.html.erb に設定
  root 'pages#home'

  mount ActionCable.server => '/cable'

  devise_for :users, 
              path: '', 
              path_names: {sign_up: 'register', sign_in: 'login', edit: 'profile', sign_out: 'logout'},
              controllers: {omniauth_callbacks: 'omniauth_callbacks', registrations: 'registrations'}

  get 'pages/home'
  get '/dashboard', to: 'users#dashboard'
  get '/users/:id', to: 'users#show', as: 'user'
  get '/your_trips' => 'reservations#your_trips'
  get '/your_reservations' => 'reservations#your_reservations'
  get 'search' => 'pages#search'
  get 'settings/payment', to: 'users#payment', as: 'settings_payment'
  get 'settings/payout', to: 'users#payout', as: 'settings_payout'
  get '/conversations', to: 'conversations#list', as: "conversations"
  get '/conversations/:id', to: 'conversations#show', as: "conversation_detail"
  
  post '/users/edit', to: 'users#update'
  post '/settings/payment', to: 'users#update_payment', as: "update_payment"
  post 'messages', to: 'messages#create'

  resources :rooms, except: [:edit] do
    member do
      get 'listing'
      get 'pricing'
      get 'description'
      get 'photo_upload'
      get 'amenities'
      get 'location'
      get 'preload'
      get 'preview'
      delete :delete_photo
      post :upload_photo
    end
    resources :reservations, only: [:create]
  end

  resources :guest_reviews, only: [:create, :destroy]
  resources :host_reviews, only: [:create, :destroy]

  resources :reservations, only: [:approve, :decline] do
    member do
      post '/approve' => "reservations#approve"
      post '/decline' => "reservations#decline"
    end
  end
  
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end



「app\channels\message_channel.rb」ファイルの記述を以下のように変更します。


記述変更 app\channels\message_channel.rb

class MessageChannel < ApplicationCable::Channel
  def subscribed
    conversation = Conversation.find params[:conversation]
    stream_for conversation
  end
end



「app\controllers\messages_controller.rb」ファイルに記述を追加します。


1.18行目から22行目の記述を以下の記述に置き換えます。

    if @message.save
      conversation.update!(updated_at: @message.created_at)
      receiver = conversation.sender.id == current_user.id ? conversation.receiver : conversation.sender
      MessageChannel.broadcast_to conversation, 
                                  sender_id: current_user.id, 
                                  sender: render_message(@message, current_user),
                                  receiver: render_message(@message, receiver)
      if URI(request.referrer).path == conversation_detail_path(id: receiver.id)
        return render json: {success: true}
      end
      redirect_to request.referrer, notice: "メッセージを送りました"
    else
      redirect_to request.referrer, alert: "メッセージを送れませんでした"
    end



2.39行目にプライベートメソッド「render_message()」を追加します。

  def render_message(message, user)
    self.render_to_string partial: 'conversations/message', locals: {m: message, user: user}
  end



記述追加 app\controllers\messages_controller.rb

class MessagesController < ApplicationController

  def create
    if current_user.id == message_params[:receiver_id]
      redirect_to request.referrer, alert: "自分にメッセージを送ることはできません"
    end
    conversation = Conversation.where("(sender_id = ? AND receiver_id = ?) OR (sender_id = ? AND receiver_id = ?)",
                                      current_user.id, message_params[:receiver_id], 
                                      message_params[:receiver_id], current_user.id
                                    ).first
    if !conversation.present?
      conversation = Conversation.create(sender_id: current_user.id, receiver_id: message_params[:receiver_id])
    end
    @message = Message.new(user_id: current_user.id, 
                           conversation_id: conversation.id,
                           content: message_params[:content]
    )
    if @message.save
      conversation.update!(updated_at: @message.created_at)
      receiver = conversation.sender.id == current_user.id ? conversation.receiver : conversation.sender
      MessageChannel.broadcast_to conversation, 
                                  sender_id: current_user.id, 
                                  sender: render_message(@message, current_user),
                                  receiver: render_message(@message, receiver)
      if URI(request.referrer).path == conversation_detail_path(id: receiver.id)
        return render json: {success: true}
      end
      redirect_to request.referrer, notice: "メッセージを送りました"
    else
      redirect_to request.referrer, alert: "メッセージを送れませんでした"
    end
  end

  private
  def message_params
    params.require(:message).permit(:content, :receiver_id)
  end

  def render_message(message, user)
    self.render_to_string partial: 'conversations/message', locals: {m: message, user: user}
  end
  
end



「app\javascript\channels\message_channel.js」ファイルを以下のように編集します。


記述編集 app\javascript\channels\message_channel.js

import consumer from "./consumer"

$(document).on('turbolinks:load', () => {
    $('[data-channel-subscribe="conversation"]').each(function(index, element) {
        var $element = $(element),
            $chatList = $('#message_list'),
            $form = $('#new_message'),

            conversation_id = $element.data('conversation-id'),
            user_id = $element.data('user-id')

        consumer.subscriptions.create(
            {
                channel: "MessageChannel",
                conversation: conversation_id
            },
            {
                received: function(data) {
                    if (data.sender_id == user_id) {
                        $chatList.append(data.sender)
                    } else {
                        $chatList.append(data.receiver)
                    }

                    $form[0].reset();
                    $chatList.animate({ scrollTop: $chatList.prop("scrollHeight") }, 1000)
                }
            }
        )
    });
});



ブラウザ確認
http://localhost:3000/conversations


メッセージを送るとリアルタイムで表示できるようになりました。

リアルタイムメッセージ
リアルタイムメッセージ



↓↓クリックして頂けると励みになります。


[48]メッセージと会話 | 会話表示<< [ホームに戻る] >> [50]通知

YAE C5 CLINIC(札幌美容クリニック)

関連記事(外部サイト)