Action Cableの習作: Examplesの更新: 3: メッセージとコメントの表示

今回は、メッセージとコメントの表示です。

1. モデルの作成
2. ユーザの認証
3. メッセージとコメントの表示
4. Action Cableの利用

メッセージとコメントの表示

Add messages and comments to routes
メッセージとコメントのルーティングを追加します。
メッセージは複数形で、indexとshowに限定します。
コメントも複数形で、createに限定します。

config/routes.rb

  resources :messages, only: %i[index show] do
    resources :comments, only: :create
  end

bin/rails routes -c messages
bin/rails routes -c comments

Show link_to messages_path in examples#index
Exampleページでメッセージ一覧のリンクを表示します。

app/views/examples/index.html.erb

...
<ul>
  <li><%= link_to 'Messages with live comments', messages_path %></li>
</ul>

bin/rails s
open localhost:3000/examples

Generate Messages controller
メッセージコントローラを生成します。

bin/rails g controller Messages index show

Show Message.all in messages#index
メッセージコントローラのindexでは、全てのメッセージを取得し、それらをテンプレートに渡します。テンプレートは渡されたメッセージのタイトルをリストで表示します。

メッセージコントローラのshowでは、引数で渡されたIDに該当するメッセージを取得し、それをテンプレートに渡します。テンプレートは渡されたメッセージのタイトルと内容を表示します。
加えて、コメントの部分テンプレートをレンダリングします。但しこの時点では対象のテンプレートは未実装です。

app/controllers/messages_controller.rb

class MessagesController < ApplicationController
  def index
    @messages = Message.all
  end

  def show
    @message = Message.find(params[:id])
  end
end

app/views/messages/index.html.erb

<h1>Messages</h1>

<ul>
  <% @messages.each do |message| %>
    <li><%= link_to message.title, message %></li>
  <% end %>
</ul>

app/views/messages/show.html.erb

<h1><%= @message.title %></h1>

<p><%= @message.content %></p>

<%= render 'comments/comments', message: @message %>

bin/rails s
open localhost:3000/messages

Show comments and form in messages#show
コメントテンプレートを配置するディレクトリを作成します。
その配下にコメント一覧表示、コメント表示、コメント作成の部分テンプレートファイルを作成します。

mkdir app/views/comments
touch app/views/comments/_comments.html.erb
touch app/views/comments/_comment.html.erb
touch app/views/comments/_new.html.erb

コメント一覧表示は、コメントの部分テンプレートレンダリングします。
属性data-message-idにメッセージID、属性data-channelに"comments"を設定します。
※オリジナルのソースコードは属性data-channelから要素を取得していますが、IDから取得しても良いと思います。

app/views/comments/_comments.html.erb

<section id="comments" data-channel="comments" data-message-id="<%= message.id %>">
  <%= render message.comments %>
</section>

<%= render 'comments/new', message: message %>

コメント表示は、ユーザ名と内容を表示します。
属性data-user-idにユーザIDを設定します。

app/views/comments/_comment.html.erb

<article data-user-id="<%= comment.user.id %>">
  <h3>Comment by <%= comment.user.name %></h3>
  <p><%= comment.content %></p>
</article>

コメント作成部分テンプレートは、コメント作成のフォームを表示します。

app/views/comments/_new.html.erb

<%= form_with model: [message, Comment.new], id: :new_comment do |form| %>
   <%= form.text_area :content, size: '100x20' %><br>
   <%= form.submit 'Post comment' %>
<% end %>

bin/rails s
open localhost:3000/messages/1

Generate Comments controller
コメントコントローラを生成します。

bin/rails g controller Comments

Create Comment in comments#create
コメントコントローラのcreateではコメントの作成を行います。

app/controllers/comments_controller.rb

class CommentsController < ApplicationController
  before_action :set_message

  def create
    @comment = Comment.create! content: params[:comment][:content], message: @message, user: @current_user
  end

  private
     def set_message
       @message = Message.find(params[:message_id])
    end
end

Refresh comment and form in messages#show
コメント作成用のテンプレートを作成します。

touch app/views/comments/create.js.erb

テンプレートでは、コメント一覧にコメントを追加し、コメント作成フォームを置換します。

app/views/comments/create.js.erb

(() => {
  const el = document.getElementById('comments')
  el.insertAdjacentHTML('beforeend', '<%=j render @comment %>')
  const new_comment = document.getElementById('new_comment')
  new_comment.outerHTML = '<%=j render "comments/new", message: @message %>'
})()

投稿したコメントが直ちに画面に表示されることを確認します。

bin/rails s
open localhost:3000/messages/1

メッセージとコメントの表示は、以上になります。

この記事が気に入ったらサポートをしてみませんか?