1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Rails】コメントの編集, 削除機能実装(form_with)

Last updated at Posted at 2022-07-16

はじめに

記事投稿アプリの記事に対して、コメントを作れる機能を実装した。
さらに、編集と削除ができるようにしたい。

完成図
完成図.gif

前提

下記は作成済み
投稿機能
ユーザーテーブル
コメントテーブル
コメントコントローラー createアクション

下記テーブルは作成済み。

No 項目 内容
1 OS Mac
2 Ruby 2.6.3
3 rails 6.0.4

ポイント

・コメント投稿機能とeditテンプレートを同じパーシャルを適用することで、dryにする。
・post_controllerに@commentを追加した。
post/show.html.erbテンプレートからコメントをする際に、
/posts/:post_id/comments/:id/edit にアクセスする時に使用するcommentモデルの主idを取得するため。
・コメントを編集、削除機能のパーシャルを作成する。

ログインユーザーがコメント作成者なら編集と削除を実行可能。
ログインユーザーが投稿作成者なら削除のみ実行可能。

routesの設定

routes.rb
  resources :posts do
    resources :comments, only: [:create, :edit, :update, :destroy]
  end

ターミナルで確認する。

post_comments         POST   /posts/:post_id/comments(.:format) comments#create
edit_post_comment GET    /posts/:post_id/comments/:id/edit(.:format) comments#edit
post_comment           PATCH  /posts/:post_id/comments/:id(.:format) comments#update
                  PUT    /posts/:post_id/comments/:id(.:format)  comments#update
                  DELETE /posts/:post_id/comments/:id(.:format)  comments#destroy

コントローラーの設定

@commentを追加した。
post/show.html.erbテンプレートからコメントをする際に、
/posts/:post_id/comments/:id/edit にアクセスする時に使用するcommentモデルの主idを取得するため。

posts_controller.rb
  def show
    @post = Post.find(params[:id])
    @comment = Comment.new # 追加
    @comments = @post.comments
  end
comments_controller.rb
  def edit
    @post = Post.find(params[:post_id])
    @comment = Comment.find(params[:id])
  end

  def update
    @post = Post.find(params[:post_id])
    @comment = Comment.find(params[:id])
    if @comment.update(comment_params)
      flash[:success] = "Comment updated"
      redirect_to @post
    else
      flash[:danger] = "Comment failed"
      render 'edit'
    end
  end

  def destroy
    @post = Post.find(params[:post_id])
    @comment = current_user.comments.find_by(post_id: @post.id)
    @comment.destroy
    redirect_to post_path(params[:post_id])
  end

  private
    def comment_params
      params.require(:comment).permit(:comment_content).merge(post_id: params[:post_id])
      #form tagにてpost_idパラメータを送信して、コメントへpost_idを格納するようにする必要がある。URLを作るために。
    end

コメント一覧表示用にcomment_usersメソッドを作る

post.rb
  has_many :comments, dependent: :destroy
  has_many :comment_users, through: :comments, source: :user

コメント投稿機能とeditテンプレートを同じパーシャルを適用することで、dryにする。
また、コメント一覧を作成し、
その中に、ユーザー情報パーシャル、コメント編集、削除機能パーシャルを作る。

show.html.erb
<%# コメント機能 %>
<p class="margin-top">コメントする</p>
  <%= render 'comments/comment_form' %> # edit.html.erbと共通のパーシャル

<p class="margin-top">コメント一覧</p>
<% @comments.each do |comment| %>
  <div class=comments>
    <%= render 'shared/user_small_info', c: comment %>
    <div class="comment_content"> <%= comment.comment_content %> </div>
    <%= render 'comments/comment_edit', post: @post, c: comment %>
  </div>
<% end %>

コメント一覧を作る

ユーザー情報のパーシャルを作成する。

app/views/shared/_user_small_info.html.erb
<%= link_to gravatar_for(c.user, size: 30), c.user %>
<span class="user">
  <%= c.user.name %>
</span>
<span class="timestamp">
  | Posted <%= time_ago_in_words(c.created_at) %> ago.
</span>

コメントを編集、削除機能のパーシャルを作成する。
・ログインユーザーがコメント作成者なら編集と削除を実行可能。
・ログインユーザーが投稿作成者なら削除のみ実行可能。

comments/_comment_edit.html.erb
<%# comment delete or edit %>
    <% if current_user?(c.user) %>
      <div class="link_to">
        <%= link_to "delete", post_comment_path(post, c), method: :delete, data: { confirm: "You sure?" } %>
          <!--comment => comment_path-->
      </div>
      <div class="link_to">
        <%= link_to "edit", edit_post_comment_path(post, c) %>
      </div>
    <%# login user が投稿者だった場合、削除のみ可能 %>
    <% elsif current_user.id == post.user_id %>
      <div class="link_to">
        <%= link_to "delete", post_comment_path(post, c), method: :delete, data: { confirm: "You sure?" } %>
          <!--comment => comment_path-->
      </div>
    <% end %>

コメント編集テンプレートを作成する。

app/views/comments/edit.html.erb
<% provide(:title, "Edit Comment") %>
<% provide(:button_text, '更新') %>

<p class="margin-top">コメントする</p>
<%= render 'comment_form' %>

編集フォームのパーシャルを作成する。
・form_withにpostモデルとcommentモデルを渡すことで、/posts/:post_id/comments/:id にアクセスするためのidを取得し、updateアクションを実行する。
・form_withにpostモデルのみ渡すことで、 /posts/:post_id/comments にアクセスするためのpost_idを取得し、createアクションを実行する。

下記を参考にした。

app/views/comments/_comment_form.html.erb
<%= form_with(model:[@post, @comment]) do |f| %>
  <%= f.text_area :comment_content %>
  <%= f.hidden_field :post_id, value: @post.id %>
  <%= f.submit yield(:button_text), class: "btn btn-primary" %>
<% end %>

おまけ

ついでに、投稿編集・削除のパーシャルも載せちゃう。

app/views/posts/_post_edit.html.erb
<% if current_user?(post.user) %>
<!--post => post_path-->
  <div class="link_to">
    <%= link_to "delete", post, method: :delete, data: { confirm: "You sure?" } %>
  </div>
  <%# 編集機能 %>
  <div class="link_to">
    <%= link_to "edit", edit_post_path(post) %>
  </div>
<% elsif current_user.id == post.user_id %>
  <div class="link_to">
    <%= link_to "delete", post, method: :delete, data: { confirm: "You sure?" } %>
  </div>
<% end %>

参考文献

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?