ratyrateを使用したRailsの星型評価を実装する


Railsで星の評価機能を実装する方法です。

環境

Rails 5.2.3
mysql
gem ratyrate
gem devise

Goals

以下のように星の評価を実装したアプリの作成
GitHub:testGemRatyrate

背景

Railsで星の評価機能を実装しようとした際、jquery.ratyを使用する方法は参考記事が沢山あるのですが、jqueryの知識を要求されたり、画像をダウンロードしたりと手間がかかります。

もっと手軽に実現できないか調べたところ、ratyrateというgemがあることを知りました。
しかし、Rails5.2.3では公式の方法ではエラーで使用することができませんでした。

そこで、Rails5.2.3で使用する方法をまとめました。

準備

ratyrateのインストール

ratyrateはjqueryを使用しているので、jquery-railsも一緒にインストールします。
また、deviseと連携させるのでdeviseも加えます。
Gemfileに以下をグローバルに記入します。

gem 'devise'
gem 'jquery-rails'
gem 'ratyrate'

インストールをします。

bundle install

評価者の設定

devise:userとratyrateを作成します。

rails g devise:install
rails g devise user
# 以下を実行すると、星画像やmigrationファイル等が作成される
rails g ratyrate user

Migration

生成されるmirationファイルは、以下の4つになります。
- db/migrate/20140814135421_create_rating_caches.rb
- db/migrate/20140706144643_create_rates.rb
- db/migrate/20140814135422_create_average_caches.rb
- db/migrate/20140814135423_create_overall_averages.rb

この状態でmigrationを実行するとエラーになり、migrationに失敗してしまいます。
そこで、各ファイルを以下のように編集します。

create_rating_caches.rb

class CreateRatingCaches < ActiveRecord::Migration[5.2]

  def self.up
      create_table :rating_caches do |t|
        t.belongs_to :cacheable, :polymorphic => true
        t.float :avg, :null => false
        t.integer :qty, :null => false
        t.string :dimension
        t.timestamps
      end
    end

    def self.down
      drop_table :rating_caches
    end

end

create_rates.rb

class CreateRates < ActiveRecord::Migration[5.2]

    def self.change
      create_table :rates do |t|
        t.belongs_to :rater
        t.belongs_to :rateable, :polymorphic => true
        t.float :stars, :null => false
        t.string :dimension
        t.timestamps
      end
    end

    def self.down
      drop_table :rates
    end

end

create_average_caches.rb

class CreateAverageCaches < ActiveRecord::Migration[5.2]

  def self.up
    create_table :average_caches do |t|
      t.belongs_to :rater
      t.belongs_to :rateable, :polymorphic => true
      t.float :avg, :null => false
      t.timestamps
    end
  end

  def self.down
    drop_table :average_caches
  end

end

create_overall_averages.rb

class CreateOverallAverages < ActiveRecord::Migration[5.2]

  def self.up
    create_table :overall_averages do |t|
      t.belongs_to :rateable, :polymorphic => true
      t.float :overall_avg, :null => false
      t.timestamps
    end
  end

  def self.down
    drop_table :overall_averages
  end
end

編集したらmigrationを実施します。

rails db:migrate

javascriptの読み込み

app/assets/javascripts/application.jsに以下を追記します。
この時、//= require rails-ujsより上に記述します。

//= require jquery
//= require jquery.raty
//= require ratyrate

以上で、ratyrateを使用する準備が整いました。

アプリ作成

実際にratyrateを実装したアプリを作成します。
作成するアプリは車のスピードを評価するものです。

準備

scaffoldを使用してモデルを作成

rails g scaffold car name:string

migrationを実施します。

rails db:migrate

コードの編集

メインとなる箇所を抜粋します。

Model

car.rb

class Car < ApplicationRecord
  ratyrate_rateable "speed" # 追加
end

補足:
ratyrate_rateableで評価対象となる項目を指定します。
複数ある場合は、カンマ区切りになります。

例:

ratyrate_rateable "speed", "engine", "price"

user.rb

class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

  ratyrate_rater # 追加
end

View

app/views/cars/show.html.erb

星を表示したい場所へ以下を記述します。

<p>Speed : <%= rating_for @car, 'speed' %></p>

以上で完成です。

その他オプション

再評価

デフォルトの設定では、一旦評価すると変更できません。
そこで以下のオプションを付けることで、評価を変更できるようになります。

<%= rating_for @car, 'speed', disable_after_rate: false %>

星の数の変更

<%= rating_for @car, 'speed', star: 10 %>

星半分

<%= rating_for @car, 'speed', disable_after_rate: false, enable_half: true %>

平均値の表示

<%= rating_for car, 'speed', disable_after_rate: true, imdb_avg: true %>

その他にもオプションが用意されているので、wazery/ratyrateRatyrate: Add Rating to Your Rails Appで確認してください。

最後に

ratyrateを使用することで、評価用のテーブルは不要になり、実装もシンプルでスマートになりました。

参考