概要
前回の続きでいいねカウントの実装をしていいねの数を表示していきたいと思います。
APIの作成
まずJavaScriptからリクエストが来たときに返したいデータを定義していきます。
JavaScriptでリクエストを送ったら現在のいいね数をresponseで返すことができれば、実装できると思いました。
いいねの数を取得するために、LikesControllerのshowアクション内でlike_countを定義
しました。
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
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
どこにいいねの数を表示するのか
.star_counter
現在
%span
がいいねをしています。
今回、star_counterクラス内のspanタグ内にいいねの数を入れていこうかと思います。span
を入れた理由はいいねの数をscss
でスタイルを調整しようと考えているからです。たとえば、以下のようにすればいいねの数だけ文字が赤く太くなります。
SCSS
.star_counter {
span {
color: red; // 好きな色
font-weight: bold; // 線を太くして強調
}
}
いいねの数を取得(GET)
JavaScriptで実装したいこととしてはまず、GETリクエストで現在のいいねの数を取得することです。
そのため、GETリクエストが成功したらいいねの数を表示させていきます。
コードにするとこのようになると思いました。 ※前回と重複するところは省略しております。
// 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要素の中身を空にするということです。これをしないとリクエストの度に要素が追加されていってしまいます。
// 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】
- Ruby 2.7.0 リファレンスマニュアル
- 【Rails】JSON形式のデータを返却する方法とは?
- jQueryで子要素を取得するいくつかの方法〜children,find,contents
- jQuery で innerHTML の書き換え/取得/追記/削除を行う方法