【rails】Ajaxでコメントを投稿する

※本サイトで紹介している商品・サービス等の外部リンクには、アフィリエイト広告が含まれる場合があります。

コメントを投稿する

先日、コメント投稿フォームを作成した

今回は、コメントを投稿し、コメント一覧にも追加表示されるようにしていく


投稿するためのボタンを用意する

articles/show.html.hamlを開く

コメント投稿ボタンにclass名をつける(add-comment-button

.container
  .btn-secondary.show-comment-form
    コメントを追加
  .comment-text-area.hidden
    = text_area_tag :comment_content, '', class: 'sm'
    .btn-secondary.add-comment-button
      コメントを投稿
  1. add-comment-buttonをクリックする
  2. 投稿フォームに入力された内容:comment_contentをajaxでpostする

投稿フォームの入力内容を取得する

投稿フォームのidはcomment_contentになっている

↑は検証ツールで確認できる

  1. add-comment-buttonがクリックされたら
  2. 投稿フォームに入力された内容を取得する
    $('#comment_content').val()
  3. 取得した内容をcontentに渡す

article.jsに以下を書く

  $('.show-comment-form').on('click', () => {
    $('.show-comment-form').addClass('hidden')
    $('.comment-text-area').removeClass('hidden')
  })

// ここから追加

  $('.add-comment-button').on('click', () => {
    const content = $('#comment_content').val()
  })

APIを作成する

まずcomments_controller.rbを開く

createアクションの不要部分を削除し、API部分を追加する

  def create
    @article = Article.find(params[:article_id])
    @comment = @article.comments.build(comment_params)
    if @comment.save
      redirect_to article_path(@article), notice: 'コメントを追加'
    else
      flash.now[:error] = '更新できませんでした'
      render :new
    end
  end

# ↓

  def create
    @article = Article.find(params[:article_id])
    @comment = @article.comments.build(comment_params)
    @comment.save!

    render json: @comment
  end

投稿フォームの入力内容に不備があった場合、javascriptでエラーが起きる

そのため、「保存できなかった場合〜」の分岐は不要になる

→必ず保存save!できるものとしてコードを書いてok!

Serializerが働いているので、@commentのみでコメントの値がjsonとして渡ってくる


postリクエストを送る

article.jsを開く

投稿フォームがブランクのときにエラーを出す

contentの中身がない場合、アラートを出す(投稿フォームがブランク)

    if (!content) {
      window.alert('コメントを入力してください')


postリクエストを送れるようにする

comments_controller.rbに、comment_paramsについて記載がある

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

これにより、コメントをpostするとき:comment:contentが必要になってくる

{comment: {content: 'コメントの内容'}}

axiosの第2引数にパラメーターを指定する

      axios.post(`/articles/${articleId}/comments`, {
        comment: {content: content}
      })

これでpostリクエストが送れるようになる


まとめると、article.jsには以下のように書く

  $('.add-comment-button').on('click', () => {
    const content = $('#comment_content').val()
    if (!content) {
      window.alert('コメントを入力してください')
    } else {
      axios.post(`/articles/${articleId}/comments`, {
        comment: {content: content}
      })
        .then((response) => {
          const comment = response.data
          $('.comments-container').append(
            `<div class="article_comment"><p>${comment.content}</p></div>`
          )
        })
    }
  })

これで、投稿フォームに入力した内容contentを取得

→ コメントを投稿して、コメント一覧に追加することができた


投稿フォームに残った値を空にする

コメント投稿したあと、投稿フォームに入力内容が残ったままになっているので空にする

          $('.comments-container').append(
            `<div class="article_comment"><p>${comment.content}</p></div>`
          )
          $('#comment_content').val('')

投稿したあと、comment_contentの中に空を入れる

→ $('#comment_content').val('')


コメント投稿についてコードをリファクタリング

投稿フォームの表示・非表示についてメソッドで定義する

const handleCommentForm = () => {
  $('.show-comment-form').on('click', () => {
    $('.show-comment-form').addClass('hidden')
    $('.comment-text-area').removeClass('hidden')
  })
}

上記が書いてあったところに以下を追加したらok

handleCommentForm()


複数回使っているコードを使い回せるように定義する

引数にはcommentを入れる

const appendNewComment = (comment) => {
  $('.comments-container').append(
    `<div class="article_comment"><p>${comment.content}</p></div>`
  )
}

上記が書いてあったところに以下を追加したらok

    .then((response) => {
      const comments = response.data
      comments.forEach((comment) => {
        appendNewComment(comment)
      })
    })

#DAY7