LoginSignup
0

More than 3 years have passed since last update.

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

Last updated at Posted at 2020-12-18

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

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

今回はこの実装のベースとなるコメント機能の基礎を実装します!
Action Cableでリアルタイムコメント機能(2/2)へ

★実装に必要な基礎知識

Action Cableとは
通常のRailsのアプリケーションと同様の記述で、即時更新機能を実装できるフレームワークです。実装内容としては、メッセージの保存や送信に必要なRubyのコーディングと、保存したメッセージを即時に表示させるJavaScriptのコーディングです。

Channelとは
チャネルとは、即時更新機能を実現するサーバー側の仕組みのことをいいます。
上記に示した通り、データの経路を設定したり、送られてきたデータをクライアントの画面上に表示させたりします。

Stream_fromとは、サーバーとクライアントを関連付けるメソッドです。Action Cableにあらかじめ用意されています。

broadcastとは、サーバーから送られるデータの経路のことを指します。
broadcastを介してデータをクライアントに送信します。

Clientや:repeat:Channel(.js/.rb):arrow_left:Server ※イメージ

★コメント機能の基礎を実装

❶routingの記述を行う

アクションはcreateとdestroyを使用する
投稿に紐づかせたいのでpostsとネストしてあげる

#routes.rb
Rails.application.routes.draw do
  devise_for :users, controllers: { registrations: 'users/registrations' }
  root to: "posts#index"
  resources :users
  resources :posts do
    resources :comments, only: [:create, :destroy]
  end
end

❷controllerの記述を行う

投稿ページにコメントを表示させる為、comments_controllerには
コメントのcreateとdestoryに関する記述のみをする

#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

posts_controllerにはコメントを表示させる為の記述を行う
今回は投稿に詳細ページを実装しているのでアクションはshow

#posts_controller
  def show
    @post = Post.find(params[:id])
    @comment = Comment.new
    @comments = @post.comments
  end

❸viewの記述を行う

renderを利用してコメントの表示部分とコメントの投稿部分を呼び出す

#show.html.erb
   <div class="row">
     <ul>
       <li class="comment-create">
         <h3 class="text-left title">トークルーム</h3>
       </li>
       <li class="comments_area">
         <%= render partial: 'comments/index', locals: { comments: @comments } %>
       </li>
     </ul>
     <% if user_signed_in? %>
       <div id="comment-create">
         <h3 class="text-left">コメントを投稿</h3>
           <%= render partial: 'comments/form', locals: { comment: @comment, post: @post } %>
       </div>
     <% end %>
    </div>

コメント表示部分

#_index.html.erb
    <% @comments.each do |comment| %>
      <% unless comment.id.nil? %>
        <li class="comment-container" id="test-<%=comment.id%>">
          <div class="comment-box">
            <div class="comment">
              <div class="comment-nickname">
                <p><%= link_to "@#{comment.user.nickname}", user_path(comment.user.id) %></p>
              </div>
                <div id="comment-entry">
                  <span style="font-weight:bold;"><%= comment.content %></span>
                    &nbsp;<%= comment.created_at.to_s(:datetime_jp) %>
                      <% if comment.user == current_user %>
                        <%= link_to post_comment_path(comment.post_id, comment.id), method: :delete, remote: true do %>
                          &nbsp;<button id="<%=comment.id%>" id="delete-btn">削除</button>
                        <% end %>
                      <% end %>
                </div>
              </div>
           </div>
        </li>
      <% end %>
    <% end %>
<!-- コメント内容(3件目以降) ------------------------------------------------------------------>
    <div class="collapse" id="collapseExample">
      <% @comments.offset(2).each do |comment| %>
        <% unless comment.id.nil? %>
          <li class="comment-container" id="test-<%=comment.id%>">
            <div class="comment-box">
              <div class="comment">
                <div class="comment-nickname">
                  <p><%= link_to "@#{comment.user.nickname}", user_path(comment.user.id) %></p>
                </div>
                  <div id="comment-entry">
                    <span style="font-weight:bold;"><%= comment.content %></span>
                      &nbsp;<%= comment.created_at.to_s(:datetime_jp) %>
                        <% if comment.user == current_user %>
                          <%= link_to post_comment_path(comment.post_id, comment.id), method: :delete, remote: true do %>
                            &nbsp;<button id="<%=comment.id%>" id="delete-btn">削除</button>
                          <% end %>
                        <% end %>
                  </div>
              </div>
            </div>
          </li>
        <% end %>
      <% end %>
    </div>

コメントの投稿部分

#_form.html.erb
<%= form_with(model: [@post, @comment], url: post_comments_path(@post.id) ) do |f| %>
    <%= f.text_area :content, class: "input-mysize" %>
    <%= f.submit "送信", class: "btn btn-outline-dark comment-submit float-right", id:"submit_btn" %>
<% end %>

modelとmigrationファイルは省略します!

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

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0