LoginSignup
1
0

More than 3 years have passed since last update.

コメント機能の実装

Posted at

備忘録です!!

Commentモデル作成

userとboardに紐ずいたcommentモデルを作成します。

ターミナル
rails g model Comment body:text user:references board:references

他モデルとのアソシエーションを追加

commentモデルとuser,boardモデルとのアソシエーションを追加します。

references型を用いたので、blongs_toは最初から記載されています。

user.rb
has_many :comments, dependent: :destroy
has_many :boards, dependent: :destroy
board.rb
has_many :comments, dependent: :destroy

ルーティングを追加

今回は、boardのルーティングをネストしていきます。

routes.rb
references :boards, only: %i[index new create show] do
  references :comments, only: %i[create], shallow: true
ターミナル
board_comments POST   /boards/:board_id/comments(.:format)                                                     comments#create
        boards GET    /boards(.:format)                                                                        boards#index
               POST   /boards(.:format)                                                                        boards#create
     new_board GET    /boards/new(.:format)                                                                    boards#new
         board GET    /boards/:id(.:format)                                                                    boards#show

shallowをtrueにしてpathを綺麗にします。

commentコントローラーを作成

ターミナル
rails g controller Comments
comments.controller
def create
  comment = current_user.comments.build(comment_params)
  comment.board_id = params[:board_id]
  if comment.save
    redirect_to board_path(params[:board_id]), success: t('defaults.message.created', item: Comment.model_name.human)
  else
    redirect_to board_path(params[:board_id]), danger: t('defaults.message.not_created', item: Comment.model_name.human)

def comment_params
  params.require(:comment).permit(:body, board_id)

コメントが保存できたら、掲示板詳細ページに移動するようにします。
この辺は、掲示板投稿機能の実装とそこまで変わりません。

boardコントローラー

掲示板の詳細ページでコメントのデータを取得します。

boards.controller
def show
  @board = Board.find(params[:id])
  @comment = current_user.comment.new
  @comments = @board.comments.includes(:user).order(created_at: :desc)

これで、コメントのデータと投稿のデータを取得でき、さらにコメントが、投稿時間順に表示されます。

viewの追加

viewを追加していきます。

今回は、コメントの表示、コメント投稿フォームはパーシャルで作成していきます。

board/show.html.erb
<div class="container pt-5">
  <div class="row mb-3">
    <div class="col-lg-8 offset-lg-2">
      <h1><%= t('.title') %></h1>
      <!-- 掲示板内容 -->
      <article class="card">
        <div id="broad-id-<%= @board.id %>">
          <div class="card-body">
            <div class='row'>
              <div class='col-md-3'>
                <%= image_tag @board.board_image.url, class: 'card-img-top img-fluid', size: '300x200' %>
              </div>
              <div class='col-md-9'>
                <h3 class="d-inline"><%= @board.title %></h3>
                  <ul class='list-inline float-right'>
                    <li class="list-inline-item">
                      <%= link_to '#', id: 'button-edit-#{board.id}' do %>
                        <%= icon 'fa', 'pen' %>
                      <% end %>
                    </li>
                    <li class="list-inline-item">
                      <%= link_to '#', id: 'button-delete-#{board.id}', method: :delete, data: {confirm: ''} do %>
                        <%= icon 'fas', 'trash' %>
                      <% end %>
                    </li>
                  </ul>
                <ul class="list-inline">
                  <li class="list-inline-item">by <%= @board.user.decorate.full_name %></li>
                  <li class="list-inline-item"><%= l @board.created_at, format: :long  %></li>
                </ul>
              </div>
            </div>
            <p><%= simple_format(@board.body) %></p>
          </div>
        </div>
      </article>
    </div>
  </div>

  <!-- コメントフォーム -->
  <%= render 'comments/form', { board: @board, comment: @comment } %>

  <!-- コメントエリア -->
  <div class="row">
    <div class="col-lg-8 offset-lg-2">
      <table id="js-table-comment" class="table">
        <%= render partial: 'comments/comment', collection: @comments %>
      </table>
    </div>
  </div>


</div>
comment/_comment.html.erb
<tr id="comment-<%= comment.id %>">
  <td style="width: 60px">
    <%= image_tag 'sample.jpg', class: 'rounded-circle', size: '50x50' %>
  </td>
  <td>
    <h3 class="small"><%= comment.user.decorate.full_name %></h3>
    <div id="js-comment-<%= comment.id %>">
      <%= simple_format(comment.body) %>
    </div>
  </td>

  <% if current_user == comment.user %>
    <td class="action">
      <ul class="list-inline justify-content-center" style="float: right;">
        <li class="list-inline-item">
          <a href="#" class='js-edit-comment-button' data-comment-id="<%= comment.id %>">
            <%= icon 'fa', 'pen' %>
          </a>
        </li>
        <li class="list-inline-item">
          <a href="#" class='js-delete-comment-button' data-comment-id="<%= comment.id %>">
            <%= icon 'fas', 'trash' %>
          </a>
        </li>
      </ul>
    </td>
  <% end %>
</tr>
comment/_form.html.erb
<div class="row mb-3">
  <div class="col-lg-8 offset-lg-2">
    <%= form_with model: [board, comment], local: true do |f| %>
      <%= render 'shared/error_messages', object: f.object %>
      <%= f.label :body %>
      <%= f.text_area :body, class: 'form-control mb-3', id: 'js-new-comment-body', row: 4, placeholder: Comment.human_attribute_name(:body) %>
      <%= f.hidden_field :board_id, value: @board.id %>
      <%= f.submit t('defaults.post'), class: 'btn btn-primary' %>
    <% end %>
  </div>
</div>

部分テンプレートの再現性が下がってしまうため、コメントの表示のパーシャルには、インスタンス変数ではなく、ローカル変数を用いました。

1
0
0

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
1
0