絶賛、プロテインの口コミ共有サービスを開発しております。
・SuppleBox(サプリボックス):https://supplebox.tokyo
その中で、Amazonなどに見られる「★による評価機能」がカッコ良いなと思ったので実装していきます。
環境
- 言語(Ruby 2.5.3)
- フレームワーク(Rails 5.2.3)
- 開発(Cloud9)
実現したいこと
1.星★による評価の入力と保存
まずは、newやeditページで★による入力と保存を行います
2.星★による評価の表示
次に、newやeditページで入力・保存した★による評価の値をshowページやindexページで表示します。
前提
- postsテーブル(口コミ投稿用のテーブル)のrateカラム(型:float)に評価値を保存する
すでに、テーブルとカラムは作成されていることを前提に進めます。
カラムは、半分の星による評価を行う場合、「0.5」や「1.5」という値を保存することになるため、float
型にしておく必要があります。
もし、integer
やstring
の型として作成してしまっていた場合は、データベースによって変更方法は異なりますが、型の変更が必要になります。
参考
jQuery Raty
Railsで星の評価を機能をつける
jQuery Ratyの使い方
javascriptの読み込み、★画像の読み込み
上記参考リンクを確認しながら、javascriptの読み込みと★画像の読み込みを行います。
星による評価の入力、保存
実装後イメージは下記。
<!-- 口コミ入力フォーム -->
<%= form_for post do |f| %>
<!--エラーメッセージ-->
<%= render 'layouts/error_messages', model: f.object %>
<!--商品コードの送信-->
<%= f.hidden_field :product_id, { value: product.id} %>
<!-- タイトル -->
<div class="form-group row">
<%= f.label :title, 'タイトル ', class:'col-md-3 col-form-label' %>
<div class="col-md-9">
<%= f.text_field :title, class: "form-control" %>
</div>
</div>
<!-- 評価 -->
<div class="form-group row" id="star">
<%= f.label :rate,'評価 ', class:'col-md-3 col-form-label' %>
<%= f.hidden_field :rate, id: :review_star %>
</div>
<!-- 評価javascript -->
<script>
$('#star').raty({
size : 36,
starOff: '<%= asset_path('star-off.png') %>',
starOn : '<%= asset_path('star-on.png') %>',
starHalf: '<%= asset_path('star-half.png') %>',
scoreName: 'post[rate]',
half: true,
});
</script>
<!-- 口コミ -->
<div class="form-group row">
<%= f.label :content, '口コミ内容 ', class:'col-md-3 col-form-label' %>
<div class="col-md-9">
<%= f.text_area :content, class: "form-control", rows: "8",
placeholder:'口コミ内容がなくても、タイトルと評価のみで投稿できます。
まずは投稿してみましょう!投稿してから編集もできますよ!' %>
</div>
</div>
<!-- 確認ボタン -->
<div class="form-group row justify-content-end">
<div class="col-md-9">
<%= f.submit '投稿する', class:"btn btn-success" %>
</div>
</div>
<% end %>
<!-- /口コミ入力フォーム -->
ポイントは下記。
# Postモデルのrateカラムに値を保存する
scoreName: 'post[rate]',
# ★の半分の入力を行う
half: true,
星による評価の表示
実装後イメージは下記。口コミ投稿一覧にて、★を表示したい。
上記の「★の入力、保存」と異なる点は、1.入力はせず表示する
、 2.繰り返し処理をする
ということになります。
<% if posts.present? %>
<% posts.each do |post| %>
<div class="row posts">
<div class="col-md-2 posts-user">
<%= link_to post.user do %>
<%= image_tag post.user.picture.url ,width: '100px' %>
<% end %>
<p class="posts-title"><%= link_to post.user.name, post.user %></p>
<p class="posts-prof"><%= post.user.gender %> <%= post.user.height %> <%= post.user.weight %></p>
</div>
<div class="col-md-6 mb-3">
<div class=" posts-content">
<p><%= simple_time(post.created_at) %></p>
<h4 class="mb-3">評価:<%= post.rate %>点 | <%= post.title %></h4>
<!--星評価-->
<div id="star-rate-<%= post.id %>"></div>
<script>
$('#star-rate-<%= post.id %>').raty({
size: 36,
starOff: '<%= asset_path('star-off.png') %>',
starOn : '<%= asset_path('star-on.png') %>',
starHalf: '<%= asset_path('star-half.png') %>',
half: true,
readOnly: true,
score: <%= post.rate %>,
});
</script>
<!--/星評価-->
<p><%= post.content %></p>
<%= image_tag post.picture.url, class:'img-fluid' if post.picture? %>
</div>
</div>
<div class="col-md-4">
<%= link_to post.product do %>
<div class="posts-product">
<img src="<%= post.product.image_url %>" alt="">
<p><%= post.product.title %></p>
</div>
<%end %>
</div>
<div class="col-md-12 edit-button">
<% if current_user == post.user %>
<%= link_to '口コミを編集', edit_post_path(post), method: :get, class:'btn btn-default' %>
<%= link_to '口コミを削除', post, method: :delete, class:'btn btn-default' %>
<% end %>
</div>
</div>
<% end %>
<% end %>
ポイントは下記。
# 繰り返し処理を実行してもidを一意に保てるようにpost.idを埋め込む
<div id="star-rate-<%= post.id %>"></div>
# 読み取り専用(入力できない)
readOnly: true,
# 星の入力値を読み込む
score: <%= post.rate %>,
豆知識
JavaScriptがうまく機能しないときは、 デベロッパーツール を見るのが重要なのですね。
どのように表示されているか確認し、デバッグしながら進めることでなんとか実装できました。
まとめ
JavaScriptを触ったのはほぼ初めてでしたが、サービスに動きをつけられてとても感動しました。
Railsの勉強が落ち着いたら、しっかり勉強したいなと感じた所存。