😎

Rails|Raty(星評価)の平均値を表示する

2023/09/10に公開

目標

Schoolに対して、Userが Reviewを投稿する。
Reviewには星評価がついている。
Schoolの詳細画面で、Schoolに対して作成された全Reviewの星評価の平均値を表示する。

開発環境

ruby 3.1.2p20
Rails 6.1.7.4
Cloud9

前提

・Deviseを導入済み(Userモデル、Adminモデルを作成済み)
・Schoolモデルを作成済み
・Reviewモデルを作成済み
・Reviewの中に星評価を作成済み
https://zenn.dev/airiin/articles/c4eabd8d91daa6

ルーティングの作成

routes.rb
  resources :schools, only: [:show]

コントローラの作成

学校詳細画面部分のコントローラを作成する。

$ rails g controller public/schools show
controllers/public/schools_controller.rb
class Public::SchoolsController < ApplicationController

  def show
    @school = School.find(params[:id])
  end

end

ビューの作成

学校詳細画面を作成する。

views/public/schools/show.html.er
  <%= render "public/reviews/average_rate.html.erb", school: @school %>

星評価の平均値部分は、部分テンプレートをレンダリングする。

星評価の平均値の部分テンプレートを作成する。

views/public/reviews/_average_rate.html.erb
<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を引数として渡すことで、指定した場所に指定したオプションで星評価を表示できる。

参考にさせていただいた記事

https://qiita.com/Bjp8kHYYPFq8MrI/items/c9663643608fdc1f841f

Discussion