LoginSignup
2

More than 1 year has passed since last update.

posted at

【Rails】コメント機能のエラーメッセージ表示方法(初学者向け)

はじめに

本記事は、駆け出しエンジニアの第一歩!AdventCalendar2020 19日目の記事です。

アプリケーション概要

ユーザー投稿に対して、コメントができる一般的なアプリケーションです。(ユーザー登録はdeviseを使用)
現状では、commentに対するバリデーションは設定していないため、空投稿が可能な状態になっています。

ER図

_2020-12-15_12.07.40.png

コメント機能

実装前のコメント機能のviewとcontrollerは以下の通りです。

post_images/show.html.erb ※コメント投稿部分のみ抜粋
<%= form_with model:[@post_image, @comment], local:true do |f| %>
  <div class="row">
    <div class="col-sm-12">
       <%= f.text_area :comment, rows:'5', class: "form-control",placeholder: "コメントをここに" %>
    </div>
  </div>
   <%= f.submit "送信する", class: "btn btn-lg btn-base-1 mt-20 pull-right" %>
<% end %>
post_images/controller.rb
def show
    @post_image = PostImage.find(params[:id])
    @comment = Comment.new
end

comments/controller.rb
def create
   post_image = PostImage.find(params[:post_image_id])
   comment = current_user.comments.new(comment_params)
   comment.post_image_id = post_image.id
   comment.save
   redirect_to post_image_path(post_image)
end

private
def comment_params
  params.require(:comment).permit(:comment)
end

コメント機能にエラーメッセージをつける

1. コメントモデルのバリデーション設定

models/comments.rb
validates :comment, presence: true

2. コントローラを条件分岐させる

ローカル変数commentのsaveに失敗した場合、commentはエラー内容を含んだものであるとわかる。その状態をviewに反映させる(エラーメッセージ を表示する)ために、インスタンス変数@error_commentにエラー内容を含んだcommentを再定義する必要がある。

comments/controller.rb
def create
    post_image = PostImage.find(params[:post_image_id])
    comment = current_user.post_comments.new(comment_params)
    comment.post_image_id = post_image.id

   #6行追加(if〜end)--------------------------------
    if comment.save
        redirect_to post_image_path(post_image)
    else
        @error_comment = comment
        render 'post_image/show'
    end
   #-----------------------------------------------
end

private
def comment_params
  params.require(:comment).permit(:comment)
end

3. エラーメッセージの表示を記載する

さっき再定義した@error_commentをviewに渡す。

post_images/show.html.erb ※コメント投稿部分のみ抜粋
<%= form_with model:[@post_image, @post_comment], local:true do |f| %>

----エラーメッセージの表示を追加------------------------------------------------
  <% if @error_comment.present? %>
    <div id="error_explanation">
      <h2><%= @error_comment.errors.count %>件のエラーが発生しました。</h2>
      <ul>
        <% @error_comment.errors.full_messages.each do |message| %>
        <li><%= message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>
--------------------------------------------------------------------------

  <div class="row">
    <div class="col-sm-12">
      <%= f.text_area :comment, rows:'5', class: "form-control",placeholder: "コメントをここに" %>
    </div>
  </div>
  <%= f.submit "送信する", class: "btn btn-lg btn-base-1 mt-20 pull-right" %>
  <% end %>

2行目の<% if @error_comment.present? %>でエラーがあるときのみ、表示されるようにする。@error_commentは、commentが空の投稿の時のみ再定義される変数のため、showページを表示するときには定義されていない。
<% if @error_comment.present? %>がないと以下のようなエラーが出る。
_2020-12-15_15.06.32.png

4. post_imageのshowアクションの内容をcreateアクションに追記する

コメント投稿が失敗した場合、post_imageのshowページへrenderするようにしてあるが、showのviewを表示するのに必要なインスタンス変数がcommentコントローラのcreateアクションにはないので、追記してやる必要がある。

post_images/controller.rb
def show
    @post_image = PostImage.find(params[:id])
    @post_comment = PostComment.new
end

追記する。

comments/controller.rb
def create
    post_image = PostImage.find(params[:post_image_id])
    comment = current_user.post_comments.new(post_comment_params)
    comment.post_image_id = post_image.id
    if comment.save
        redirect_to post_image_path(post_image)
    else
        @error_comment = comment

#------post_imageのshowアクションを追加---------------
        @post_image = PostImage.find(params[:id])
        @post_comment = PostComment.new
#-------------------------------------------------
        render 'post_image/show'
    end
end

private
def comment_params
  params.require(:comment).permit(:comment)
end

これでコメント投稿を実行しても、idがないので見つけることができないという以下のようなメッセージが出る。正確にはidはあるけど名称が変わって違うものになっているのでidを見つけることができないという感じ。_2020-12-15_15.19.57.png
rails routesで確認すると、

Prefix Verb URI Pattern Controller#Action
post_image GET /post_images/:id(.:format) post_image#show
post_image_comments POST /post_images/:post_image_id/comments(.:format) comment#create

showアクションではpost_imagesのパラメーターidは:idであったが、createアクションの場合、パラメーターidはpost_image_idとなっている。そのため、パラメーターidをpost_image_idに変更する。

comments/controller.rb
def create
    post_image = PostImage.find(params[:post_image_id])
    comment = current_user.post_comments.new(post_comment_params)
    comment.post_image_id = post_image.id
    if comment.save
        redirect_to post_image_path(post_image)
    else
        @error_comment = comment
 #----------変更(:id → :post_image_id)------------------------
        @post_image = PostImage.find(params[:post_image_id])
 #------------------------------------------------------------
        @post_comment = PostComment.new
        render 'post_image/show'
    end
end

private
def comment_params
  params.require(:comment).permit(:comment)
end

_2020-12-15_15.37.08.png

まとめ

非常に回りくどい説明になりましたが、初学者の方でエラー解決に苦労している方などの参考になれば幸いです。

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
What you can do with signing up
2