【Rails】Ajaxでいいねの数を表示する方法

## 概要
[前回の続き](https://qiita.com/suzu12/items/7b72b87a34fa7e2d1307)でいいねカウントの実装をしていいねの数を表示していきたいと思います。

## APIの作成
まずJavaScriptからリクエストが来たときに返したいデータを定義していきます。
JavaScriptでリクエストを送ったら現在のいいね数をresponseで返すことができれば、実装できると思いました。

いいねの数を取得するために、`LikesControllerのshowアクション内でlike_countを定義`しました。

```ruby:app/controllers/likes_controller.rb
def show
  like_count = @team.likes.count
  render json: { likeCount: like_count }
end
```

#### ただ、私が実装したいことは

**現在のいいね数を`DOMContentLoaded`イベント時に取得することだけでなく、POSTとDELETEのリクエストの時にも取得したいと考えています。**
そのため、**showアクション内にだけ**定義するのではなく`create`, `destroy`にも定義していく必要があります。`create`と`destroy`でも`render json`に`likeCount`を入れないと**JavaScriptからのリクエストに対応するデータがないのでundefined**になって返ってきてしまいます。

前回と重複するところもありますが、`LikesController`の記述はこのようになると思いました。`before_action :like_counts`でアクションの最初に読み込むようにしています。

#### LikesController

```ruby:app/controllers/likes_controller.rb
class LikesController < ApplicationController
  before_action :authenticate_user!
  before_action :set_like
  before_action :like_counts

  def show
    like_status = current_user.has_liked?(@team)

    render json: { hasLiked: like_status, likeCount: like_counts }.to_json
  end

  def create
    @team.likes.create!(user_id: current_user.id)

    render json: { status: 'ok', likeCount: like_counts }.to_json
  end

  def destroy
    like = @team.likes.find_by!(user_id: current_user.id)
    like.destroy!

    render json: { status: 'ok', likeCount: like_counts }.to_json
  end

  private

  def set_like
    @team = Team.find(params[:team_id])
  end

  def like_counts
    @like_count = @team.likes.count
  end
end
```

## どこにいいねの数を表示するのか

```haml:show.html.haml
.star_counter
  現在
  %span
  がいいねをしています。
```

今回、**star_counterクラス内のspanタグ内**にいいねの数を入れていこうかと思います。`span`を入れた理由はいいねの数を`scss`でスタイルを調整しようと考えているからです。たとえば、以下のようにすれば**いいねの数だけ文字が赤く太く**なります。

#### SCSS

```scss:scss
.star_counter {
  span {
    color: red; // 好きな色
    font-weight: bold; // 線を太くして強調
  }
}
```


## いいねの数を取得（GET）

JavaScriptで実装したいこととしてはまず、GETリクエストで現在のいいねの数を取得することです。
そのため、GETリクエストが成功したらいいねの数を表示させていきます。

コードにするとこのようになると思いました。　**※前回と重複するところは省略しております。**

```javascript:jQuery
// GET, POST, DELETEリクエストで使うので処理をまとめています。
const likeCountCalculation = (likeCount) => {
// いいねの数を表示させたいところを取得。今回はstar_counterクラス内のspan要素を取得しています。その後appendで追加していくという処理です。
  $('.star_counter > span').append(
    `${likeCount}人`
  )
}

// axiosでGETリクエスト成功
.then((response) => {
// response内に先程Controllerで書いたlikeCountがjson形式で返されるので取得。
  const likeCount = response.data.likeCount
// 上で定義してあるlikeCountCalculation(）が呼び出されて、span要素内に現在のいいねの数が表示されるようになります。現在のいいねの数はlikeCountに入っているので関数を呼び出すときにを引数にいれています。
  likeCountCalculation(likeCount)
})
```

## いいねの数の増減 (POST, DELETE)

はじめは、`likeのcountを+1, -1`することで実装すればと思っていたのですが、それよりもGETの処理と同じ考え方で現在のいいねの数を取得すれば良いのでは？と考えました。現在のというのは**+1や-1されたあとのいいねの数のこと**です。要するに、**POSTやDELETEリクエストが成功すればいいねの数は増減しているのでその値を取得**することで実装できると思いました。
コードにするとこのようになると思います。POSTもDELETEも同じ記述なのでまとめて書かせていただきます。GETの処理と違う点は、**リクエストが成功したらspan要素の中身を空にする**ということです。これをしないとリクエストの度に要素が追加されていってしまいます。

```javascript:jQuery
// axiosでリクエスト（POST or DELETE)成功
.then((response) => {
  // responseに入ってくるいいねの数を取得
  const likeCount = response.data.likeCount
  // star_counterクラス内のspan要素の中身を空にする。
  $('.star_counter > span').html('')
  // 現在いいねの数を表示する。
  likeCountCalculation(likeCount)
})
```

## まとめ
- 前回同様やりかたは一つではないこと。
- 親要素内の子要素を取得する方法もひとつではなく選択肢がたくさんあり、わかりやすいものを使う。（読みやすいコードだったり状況に応じて判断）
- jsonで複数の値を返すには記述を変える必要がある。

## 最後に
自分の実装したいことをどうやって実現していくのか、ここの言語化が大事だと感じました。実装したいことに対して、いくつもの方法があるということは、簡単に書けるものだったり逆に複雑になってしまったりすることがあると思います。こういったところもたくさんコードを書いたり技術書を読んだり、記事を見たりして学習していくことで力をつけていきます。

## 参考文献

- [length、size、count メソッドの違いまとめ【Ruby】](https://qiita.com/motoki4917/items/ffc89d955e20b91d1014)
- [Ruby 2.7.0 リファレンスマニュアル ](https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/count.html)
- [【Rails】JSON形式のデータを返却する方法とは？](https://pikawaka.com/rails/json)
- [jQueryで子要素を取得するいくつかの方法〜children,find,contents](https://www.flatflag.nir87.com/children-996#children)
- [jQuery で innerHTML の書き換え／取得／追記／削除を行う方法](https://webllica.com/jquery-innerhtml-edit-get-add-del/)


##### 前回書いた記事です。いいねの実装をこちらでしているのでよろしければご覧ください！

- [【Rails】いいね機能をjQueryで実装](https://qiita.com/suzu12/items/7b72b87a34fa7e2d1307)