はじめに
- 投稿詳細ページの閲覧数をカウントし、投稿一覧と投稿詳細に表示させる
- 学習内容の備忘録です
前提条件
- ユーザーと投稿に関する機能が実装できている
- ここでは、UsersテーブルとBooksテーブルがある状態
- Bootstrap4を入れている状態
手順
- モデル作成
- アソシエーション
- コントローラ
- ビュー
1.モデル作成
今回作成するモデルはLookモデルとします。
rails g model Look user_id:integer book_id:integer
migrationファイルを確認し、問題なければ、
rails db:migrate
2.アソシエーション
belongs_to :user
belongs_to :book
validates_uniqueness_of :book_id, scope: :user_id
補足
「validates_uniqueness_of :book_id, scope: :user_id」によって、同じ本(book_id)に対して同じ人(user_id)の閲覧カウントが重複しないようにしている。
has_many :looks, dependent: :destroy
has_many :looks, dependent: :destroy
1人のユーザーは複数の閲覧データを持ち、1冊の本も複数の閲覧データを持つ。
user:book=N:N
user:look=1:N
book:look=1:N
のアソシエーションが完成!
3.コントローラー
ここでは、booksコントローラーに閲覧数をカウントさせる記述を書く。
(bookの閲覧数なので、looksコントローラーは作成しない)
def show
#省略
# ゲストユーザーログインを実装しているため、ゲストユーザーでない時に限定
if current_user.name != "guestuser"
# Lookの中にbook_idとユーザーのidが一致するものがないか探し、unlessによって、falseの場合のみ実行する
unless Look.find_by(user_id: current_user.id, book_id: @book.id)
# このユーザーのlooksを新たに作成し、book_idに取得してきた本のidを入力
current_user.looks.create(book_id: @book.id)
end
end
end
補足
今回は1人1カウントにしたが、1日1カウントにしたい場合は、
「where(created_at: Time.zone.now.all_day)」で、可能になる。
参考にさせていただきました
4.ビュー
今回は、閲覧数をカウントし表示する記述は、部分テンプレートにまとめた。
# user_has_look?メソッドはbookモデルに定義する
<% if current_user && book.user_has_look?(current_user) %>
<div class="text-danger"> # 閲覧した場合は、赤色に
閲覧数:<%= book.looks.count %>
</div>
<% else %>
<div class="text-dark"> # 閲覧していない場合は、黒色に
閲覧数<%= book.looks.count %>
</div>
<% end %>
user_has_look?メソッドの定義をしておく
# userを引数にし、user_idにこのユーザーのidが存在するかを確認する
def user_has_look?(user)
looks.where(user_id: user.id).exists?
end
あとは、この部分テンプレートを呼び出したいところへ!
(ここでは、本の一覧表示についても部分テンプレートに記述している。)
# 省略
<% books.each do |book| %>
# 省略
# 閲覧数を表示したい部分に記述
<%= render partial: "books/look", locals: { book: book } %>
詳細ページにも!
# 閲覧数を表示したい部分に記述
<%= render partial: "books/look", locals: { book: @book } %>
まとめ
- 閲覧カウントは、ユーザーと投稿に中間テーブルを設ける
- 投稿に関するコントローラーでidを作成する
⚠️学習4ヶ月目の初学者による投稿です。
⚠️間違いがあるかもしれません。ご容赦ください。
⚠️ご指導、ご教授いただけると幸いです。