#はじめに
Raty.jsというものを使い、コメント形式で投稿を星評価できるようにします。
また、多数のユーザーからの星評価の平均を出力することもできたので、そちらも合わせて紹介します。
#使用環境
Ruby on Rails 6
#前提
・CRUD機能を実装している事
・deviseを導入している事
・コメント機能を実装している事
#モデルの設計
・Userモデル(deviseで作成)
・Tweetモデル
・Commentモデル
#Commentモデルにrateカラムを設置
rails g migration AddRateToComments rate:float
Raty.jsを用いる際にはrateカラムが大切になってきます。今回は「星1.5」などにも対応するため、float型を用いています。
#Commentモデルにバリデーションを追加
validates :rate, numericality: {
less_than_or_equal_to: 5,
greater_than_or_equal_to: 1}, presence: true
ここでは、星が1~5までで保存できるようになっています。
#表示するために星の画像を追加
https://github.com/wbotelhos/raty/tree/master/lib/images
ここから星の画像をダウンロードできます!ダウンロードした画像は、「app/assetes/images」直下に保存します。
#jQueryの導入
yarn add jquery
yarn addコマンドは、パッケージのインストールと共に、package.jsonへバージョンを書き込んでくれます。
次に、webpackerの設定ファイルで、jQueryを管理下に追加するための記述をします。
const { environment } = require('@rails/webpacker')
追記
const webpack = require('webpack')
environment.plugins.prepend('Provide',
new webpack.ProvidePlugin({
$: 'jquery/src/jquery',
jQuery: 'jquery/src/jquery',
jquery: 'jquery/src/jquery',
})
)
ここまで
module.exports = environment
最後に、jQueryを呼び出します。
省略
window.$ = window.jQuery = require('jquery'); 追記
#Raty.jsの導入
app/javascript/packsにraty.jsというファイルを作成します。
次に下記URLのjsコードをraty.jsにコピーする。
https://github.com/wbotelhos/raty/blob/master/lib/jquery.raty.js
最後にapplication.js に下記を追加します。
window.$ = window.jQuery = require('jquery');
require('packs/raty') 追記
#Controller設計
省略
def show
@tweet = Tweet.find(params[:id])
@comments = @tweet.comments
@comment = Comment.new
end
省略
def create
tweet = Tweet.find(params[:tweet_id])
comment = tweet.comments.build(comment_params) #buildを使い、contentとtweet_idの二つを同時に代入
comment.user_id = current_user.id
if comment.save
flash[:success] = "コメントしました"
redirect_back(fallback_location: root_path)
else
flash[:success] = "コメントできませんでした"
redirect_back(fallback_location: root_path)
end
end
private
def comment_params
params.require(:comment).permit(:content, :rate)
end
#View設計
<div class="average-review-rating" data-score=<%= @comments.average(:rate) %>></div>
<script>
$('.average-review-rating').raty({
readOnly: true,
starOn: "<%= asset_path('star-on.png') %>",
starOff: "<%= asset_path('star-off.png') %>",
starHalf: "<%= asset_path('star-half.png') %>",
score: function() {
return $(this).attr('data-score')
}
});
</script>
<%= render 'rate_average' %>
<div class="comment-container">
<% @comments.each do |c| %>
<div class="pt-2 px-2" style="background-color: #fffffe; border: 2px solid #272343; border-radius: 2px;">
<div class="review-rating" data-score="<%= c.rate %>">評価:<%= c.rate %></div>
<div class="text-left">
<p>投稿者:<%= c.user_id %></p>
<p><%= c.content %></p>
</div>
<div class="text-right">
<p>
投稿日:<%= c.created_at.strftime('%Y/%m/%d') %>
</p>
</div>
</div>
<div class="pb-2"></div>
<% end %>
<%= form_with(model: [@tweet, @comment], local: true) do |f| %>
<%= f.text_area :content, rows:'5', placeholder: "コメント", class: "form-control form-control-sm" %>
<div id="rating-form">
<label>評価:</label>
<%= f.hidden_field :rate, :value => 'score' %>
</div>
<%= f.submit "投稿する" %>
<% end %>
</div>
<script>
$('#rating-form').raty({
starOn: "<%= asset_path('star-on.png') %>",
starOff: "<%= asset_path('star-off.png') %>",
scoreName: 'comment[rate]'
});
</script>
#参考記事
https://nllllll.com/ruby-on-rails/rails-raty-js-review/
https://qiita.com/nozomi_nozomi/items/eb6848c6025ca63af1c4