Rails|Raty(星評価)の平均値を表示する
目標
Schoolに対して、Userが Reviewを投稿する。
Reviewには星評価がついている。
Schoolの詳細画面で、Schoolに対して作成された全Reviewの星評価の平均値を表示する。
開発環境
ruby 3.1.2p20
Rails 6.1.7.4
Cloud9
前提
・Deviseを導入済み(Userモデル、Adminモデルを作成済み)
・Schoolモデルを作成済み
・Reviewモデルを作成済み
・Reviewの中に星評価を作成済み
ルーティングの作成
resources :schools, only: [:show]
コントローラの作成
学校詳細画面部分のコントローラを作成する。
$ rails g controller public/schools show
class Public::SchoolsController < ApplicationController
def show
@school = School.find(params[:id])
end
end
ビューの作成
学校詳細画面を作成する。
<%= render "public/reviews/average_rate.html.erb", school: @school %>
星評価の平均値部分は、部分テンプレートをレンダリングする。
星評価の平均値の部分テンプレートを作成する。
<div id="star_<%= school.id %>"></div>
<script>
$(document).on('turbolinks:load', function() {
let elem = document.querySelector('#star_<%= school.id %>');
if(elem == null) return;
elem.innerHTML = ""
let opt = {
starOn: "<%= asset_path('star-on.png') %>",
starOff: "<%= asset_path('star-off.png') %>",
starHalf: "<%= asset_path('star-half.png') %>",
score: <%= school.reviews.average(:star_integer).to_f.round(1) %>,
readOnly: true,
};
raty(elem, opt);
});
</script>
<div id="star_<%= school.id %>"></div>
このdiv
部分に、星マークが表示される。
$(document).on('turbolinks:load', function() {...}
この部分で、Turbolinksでページが読み込まれた時に実行されるようにしている。
document.querySelector
指定したセレクターに合致する最初の要素を取得する関数。
let elem = document.querySelector('#star_<%= school.id %>');
ここで、最初に作成したdiv
が elemに代入されている。
if(elem == null) return;
elem が見つからなかった場合、関数を終了させる。
elem.innerHTML = ""
elem の内部のHTMLを空にする。
let opt = {...}
星評価の表示オプションを optという変数に定義している。
starOn:
/ starOff:
/ starHalf
星評価が付与された/付与されていない/半分付与された星の画像のパスを指定。
score:
表示する星評価の数値
<%= school.reviews.average(:star_integer).to_f.round(1) %>
学校のレビュー全体の平均の星評価を計算し、小数点第1位までに収めている。
readOnly: true
読み取り専用に設定している。そのため、ユーザーはこの星評価を変更できない。
raty(elem, opt);
raty
は星評価を表示するための関数。elemとoptを引数として渡すことで、指定した場所に指定したオプションで星評価を表示できる。
参考にさせていただいた記事
Discussion