🐯

【Ruby on Rails】コメント編集機能の実装

2024/07/03に公開

2024/1からプログラミングスクールに通っている、プログラミング初学者です。
2024/6/28より自分自身のアウトプットのために、はてなブログで毎日投稿をしています。
初学者の投稿になるため間違い等ございましたら、優しくご指摘いただけますと幸いです。

はじめに

現在RubyonRailsを使用して、記事投稿機能の作成および、その投稿に対してコメントできる機能を実装しています。今回、コメントの編集削除機能を実装している中で、編集機能を追加する際に少し手間取りましたので、その備忘録となります。(削除機能の説明はしておりません)
参考になりましたら幸いです。

結論

コメントの編集機能で、createアクションとupdateアクションでストロングパラメータの内容を分けることにより、データの受け渡しに成功しました。
この方法が正しいのかは分かりませんが、挙動としてはコメント編集ができるようになったため今回記事を書いております。

エラーが起きた時の状況

  • config/routes.rb
    ルーティング設定は下記の通りです。
    articleルーティングにネストした形で、favoriteとcommmentルーティングを設定しています。
resources :articles do
  resources :favorites, only: [:create, :destroy]
  resources :comments, shallow: true 
    end
  • app/controllers/comments_controller.rb
    エラー発生時、修正前のcommentsコントローラーになります。
class CommentsController < ApplicationController
  before_action :set_comment, only: [:edit, :update, :destroy]
  def index
    @comment = Comment.new
  end

  def create
    @comment = current_user.comments.build(comment_params)
    @comment.save
    redirect_to article_path(@comment.article_id)
  end

  def show
    @comment = Comment.find(params[:id])
  end

  def edit; end

  def update
    if @comment.update(comment_params)
      redirect_to article_url
    end
  end

  def destroy
    @comment.destroy!
    redirect_to article_path(@comment.article_id)
  end
  

  private

  def comment_params
    params.require(:comment).permit(:body).merge(article_id: params[:article_id])
  end

  def set_comment
    @comment = current_user.comments.find(params[:id])
  end
end
  • app/views/comments/edit.html.erb
    コメント編集画面のため、form_withの送信先はcomment_path(@comment)とし、編集画面に遷移させています。
<%= form_with model: @comment, url: comment_path(@comment) do |form| %>
  <%= form.label :body, "コメント"%>
  <%= form.text_area :body, placeholder: 'コメント', class: "textarea textarea-bordered w-full mb-4 h-full bg-white text-gray-600" %>
  <%= form.submit "投稿する", class: "mt-10 flex w-full justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"%>
<% end %>

ここまで実装したところで、編集内容が保存されずサーバーログ上でエラーが出てしまいました....。
Image from Gyazo

画面上でわかる通り、commentsコントローラーのupdateアクションでデータがrollbackされてしまい、
ActiveRecord::RecordInvalid(Validation failed: Article must exist):というエラーが出てしましまいました。

どのようにエラーを解決したか

下記にどのようにエラーを解決したか手順を記載します。少し回り道をしてしまいましたが、勉強になりました。

1, エラー文をそのまま検索する
エラーが出てネット検索にかけました。(皆様そうだと思いますが....)
今回のエラー文で出てきた記事では、optional: trueという、モデル内でのbelongs_toの外部キーのnilを許可するオプションを設定すれば解決できる、というものがほとんどでした。
私の場合はこのオプションをつけても、エラーは変わらないままでした。
(もしかしたら設定している箇所が間違っていたのかもしれません...)

2, 再度サーバーログを確認する
エラーが発生したのが夜分ということもあり、エラー解消は次の日に取り組みました。
再度サーバーログを確認したところ、やはりcommentsコントローラーのupdateアクションでrollbackが起きているので、もう一度コントローラーを見直しました。

def update
    if @comment.update(comment_params)
      redirect_to article_url
    end
  end

- 省略 -

 def comment_params
    params.require(:comment).permit(:body).merge(article_id: params[:article_id])
  end

ActiveRecord::RecordInvalid(Validation failed: Article must exist):というエラーのため、ものは試しにということで、ストロングパラメータ内の.merge(article_id: params[:article_id])の記述を消してみました。

すると、データのcommitすら始まらない状況...。ということは、このストロングパラメータが怪しいと仮説を立てました。一旦.merge(article_id: params[:article_id])を消してみると、処理が走らなくなってしまうのでupdateアクションだけ別のストロングパラメータを作れないのか?と気になりました。

そもそもストロンングパラメータが複数作成できるのか知らなかったので、調べてみるとこちらの記事を発見し、なんとか実装できるのでは?と思い、下記へ変更しました。

結果、アクションごとにストロングパラメータの記述を書き換えることで、コメントの編集ができるようになりました。

def create
    @comment = current_user.comments.build(create_comment_params)
    @comment.save
    redirect_to article_path(@comment.article_id)
  end

  - 省略 -

  def edit; end

  def update
    if @comment.update(update_comment_params)
      redirect_to article_url
    end
  end

private

  def create_comment_params
    params.require(:comment).permit(:body).merge(article_id: params[:article_id])
  end

  def update_comment_params
    params.require(:comment).permit(:body)
  end
end

しかし現状では、コメント編集機能の非同期処理は未実施なので、また記述が変わる可能性もありますが、一旦コメント編集ができる状況になり、エラー解消できたので備忘録として残しておきます。
改めてサーバーログを確認し、仮説検証を立てる重要性を認識しました。
ありがとうございました。

Discussion