Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
0
Help us understand the problem. What are the problem?

posted at

updated at

Action Cableでリアルタイムコメント機能(2/2)

★Action Cableでリアルタイムコメント機能を実装する

新たにチャットルームは作成せずに投稿に紐づいたコメント機能として
リアルタイムでコメントの投稿、削除が可能な実装を行う

今回はリアルタイムコメント機能を実装する
下記リンクでActionCableについて少しまとめている
コメント機能の基礎(1/2)へ

❶controllerを確認する

コメントのcreateとdestroyを行った後
javascriptへデータとして送りたい情報をここで指定する

#comments_controller.rb
class CommentsController < ApplicationController
  def create
    @post = Post.find(params[:post_id])
    #投稿に紐づいたコメントを作成
    @comment = @post.comments.build(comment_params)
    @comment.user_id = current_user.id
    if @comment.save
      ActionCable.server.broadcast 'message_channel', content: @comment, user: @comment.user, date: @comment.created_at.to_s(:datetime_jp), id: @comment.id,post: @comment.post
    end
  end

  def destroy
    @post = Post.find(params[:post_id])
    @comment = Comment.find(params[:id])
    if @comment.destroy
      ActionCable.server.broadcast 'delete_channel', id: @comment.id
    end
  end

  private
  def comment_params
    params.require(:comment).permit(:content, :post_id, :user_id).merge(user_id: current_user.id)
  end
end

❷channelでcontrollerとjavascriptファイルを繋げる

#message_channel.rb
class MessageChannel < ApplicationCable::Channel
  def subscribed
    stream_from "message_channel"
  end

  def unsubscribed
    # Any cleanup needed when channel is unsubscribed
  end
end
#delete_channel.rb
class DeleteChannel < ApplicationCable::Channel
  def subscribed
    stream_from "delete_channel"
  end

  def unsubscribed
    # Any cleanup needed when channel is unsubscribed
  end

end

❸javascriptでリアルタイムで実装したい処理を記述する

日時の表示をformatで指定したものにする
文字列の中にコードを埋め込む記法について整理

#message_channel.js
import consumer from "./consumer"
window.addEventListener('load', function(){

consumer.subscriptions.create("MessageChannel", {
  connected() {
    // Called when the subscription is ready for use on the server
  },

  disconnected() {
    // Called when the subscription has been terminated by the server
  },

  received(data) {
    const html = `<div id="test-${data.id}">
    <p><a href="/users/${data.user.id}">@${data.user.nickname}</a></p>
                  <span style="font-weight:bold;">${data.content.content}</span>
                  &nbsp;${data.date}
                  &nbsp;<a id="delete-btn", data-method="delete" href="/posts/${data.post.id}/comments/${data.id}"><button id="${data.id}">削除</button></a>
                  </div>`;

    const messages = document.getElementById('collapseExample');
    const newMessage = document.getElementById('comment_content');
    messages.insertAdjacentHTML('beforeend', html);
    newMessage.value='';

      var countComment = document.getElementsById('collapseExample').length;
      console.log(countComment)
  }
});
})

delete_channel.jsの流れ
コメントのコンテナ要素にあらかじめコメント ID を入れておいて

#_index.html.erb
<li class="comment-container" id="comment-#{comment.id}">

これを見つけてあげて削除をする

また、(comment-${data.id})とすることで
コメントのIDのみを取得している
コントローラーで@comment.idで送信しているので、する必要はないと思うが
id:137のように137だけでなく余計な部分も送信されていたため指定を細かくした

debuggerを小まめに使い、確認しつつ実装することが重要

#delete_channel.js
import consumer from "./consumer"
window.addEventListener('load', function(){
consumer.subscriptions.create("DeleteChannel", {
  connected() {
    // Called when the subscription is ready for use on the server
  },

  disconnected() {
    // Called when the subscription has been terminated by the server
  },

  received(data) {

    const test = document.getElementById(`${data.id}`)
    const container = document.getElementById(`test-${data.id}`);
    console.log(container)
    container.remove();

    },

});
})

★今回実装した削除機能の別プランは以下が考えられる

insertAdjacentHTML で要素を挿入した後、その要素に onclick イベントハンドラを追加してハンドラ内で削除のリクエストを送る

JQueryを使用すれば記述を短くできるが、今回は勉強の為にJavascriptのみで実装した

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
0
Help us understand the problem. What are the problem?