I would like to rank the memo apps that I am developing. This time, I will evaluate it in three stages. Along with that, you will learn about inputting, saving, and displaying evaluations by stars.
Add star rating function with Rails
Save the evaluation value in the rate column (type: float) of the notes table (memo table) We will assume that the tables and columns have already been created.
The column should be float type because it will store values such as "0.5" and "1.5" when evaluating with half a star.
If you have created it as an integer or string type, you will need to change the type, although the change method differs depending on the database. The article below describes a solution when you're addicted to this type of change swamp.
class CreateNotes < ActiveRecord::Migration[5.2]
  def change
    create_table :notes do |t|
      t.text :title
      t.integer :user_id
      t.integer :category_id
      t.text :explanation
      t.float :rate
      t.timestamps
    end
  end
end
rails db:migrate:reset
While checking the above reference link, load javascript and load the star image.
Method (2 types)
① To use jQuery Raty, download jquery.raty.js from https://github.com/wbotelhos/raty.
Place the downloaded script anywhere on your website.
Place the downloaded jquery.raty.js file in the app / javascripts folder
(2) Load JavaScript in HTML that uses jQuery Raty. Since Raty is a jQuery plugin, you also need a jQuery script.
    <script src="/js/jquery.min.js"></script>
    <script src="/js/jquery.raty.js"></script>
This time, we will implement it by the method of ①.
javascripts / application.js file//= require rails-ujs
//= require activestorage
//= require turbolinks
//= require jquery       #add to
//= require jquery_ujs  #add to
//= require_tree .
Add Gem file
gem 'jquery-rails'
budle install
note.rb
class Note < ApplicationRecord
  #Linking with users
  belongs_to :user,optional: true
 #Validation
  validates :title, presence: true
  validates :explanation, presence: true
  
  #Link with category
  belongs_to :category
  validates :rate, presence: true
  validates :rate, numericality: {
    # only_integer: true,
    less_than_or_equal_to: 3,
    greater_than_or_equal_to: 1,
  }
# Numericality = allow the sky
numericality also allows decimals by default. I only want to allow integers in the rate column, so only_integer.
Example
   validates :param3, :numericality => { :less_than_or_equal_to => 3}
   #Is the number 3 or less?
   validates :param3, :numericality => { :greater_than_or_equal_to => 1 }
   #Is the number 1 or more?
end
notes_controller.rb
class NotesController < ApplicationController
  before_action :authenticate_user!
  def new
    @note = Note.new
  end
  def create
    # @note = Note.new(note_params)
    @note = current_user.notes.build(note_params)
    @note.save
    redirect_to notes_path
  end
  def index
    # is_Get all records that valid matches
    @categorys = Category.where(is_valid: true)
    @q = Note.all.ransack(params[:q])
    @notes = @q.result(distinct: true)
  end
  def show
    @note = Note.find(params[:id])
  end
  def edit
    @note = Note.find(params[:id])
  end
  def update
    @note = Note.find(params[:id])
    @note.update(note_params)
    redirect_to note_path
  end
  def destroy
    @note = Note.find(params[:id])
    @note.destroy
    redirect_to notes_path
  end
  def search
    @categorys = Category.where(is_valid: true)
    @category = Category.find(params[:id])
    @q = @category.notes.all.ransack(params[:q])
    @notes = @q.result(distinct: true).page(params[:page])
    @title = @category.name
    render 'notes/index'
  end
  private
  def note_params
    params.require(:note).permit(:title, :category_id, :explanation,:user_id,:rate)
  end
end
Here we add a rate column to the note_params method.
_form.html.erb
<%= form_with model:note, local: true do |f| %>
  <div class='form-group'>
    <%= f.label :title%>
    <%= f.text_field :title, class: 'form-control', id: 'note_title' %>
  </div>
  <div class='form-group'>
    <%= f.label :Category%>
    <%= f.collection_select :category_id, Category.all, :id, :name %>
  </div>
  <!--Evaluation-->
  <div class="form-group row" id="star">
    <%= f.label :rate,'importance', class:'col-md-1 col-form-label' %>
    <%= f.hidden_field :rate, id: :review_star %>
  </div>
  <div class='form-group'>
    <div id='editor'>
      <%= f.label :Contents%>
      <%= f.text_area :explanation, rows: 10, class: 'form-control', id: 'note_explanation', "v-model" => "input", name: "note[explanation]" %>
    <h2><i class="fas fa-eye"></i> Preview</h2>
    <div id="preview-field" v-html='input | marked'>
    </div>
    <div ></div>
  </div>
  <%= f.submit 'Registration', class: 'btn btn-success' %>
  </div>
  <% end %>
  <!--Real-time preview-->
  <script type="text/javascript">
    window.onload = function() {
      new Vue({
      el: '#editor',
      data: {
        input: '<%== j @note.explanation %>',
      },
      filters: {
      marked: marked,
      },
      });
    };
   <!--Evaluation-->
    $('#star').raty({
      size     : 36,
      starOff:  '<%= asset_path('star-off.png') %>',
      starOn : '<%= asset_path('star-on.png') %>',
      starHalf: '<%= asset_path('star-half.png') %>',
      scoreName: 'note[rate]',
      half: true,
    });
  </script>
To be able to input half of # ★ half: true,
I want to display ★ in the memo list. The difference from the above "Enter and save ★" is that 1. Display without input, 2. Repeat processing.
_notes_index.html.erb
<div class='row'>
  <table class='table'>
    <thead>
      <tr>
        <th>title</th>
        <th>Category</th>
        <th>importance</th>
      </tr>
    </thead>
    <tbody>
      <% @notes.each do |note| %>
      <% if user_signed_in? && current_user.id == note.user_id %>
      <tr>
        <td>
          <%= link_to note_path(note) do %>
            <%= note.title %>
          <% end %>
        </td>
        <td><%= note.category.name %></td>
        <!--Evaluation-->
     <td>
         <div id="star-rate-<%= note.id %>"></div>
          <script>
            //Note so that id can be unique even in iterative processing_enter id
          $('#star-rate-<%= note.id %>').raty({
            size: 36,
            starOff:  '<%= asset_path('star-off.png') %>',
            starOn : '<%= asset_path('star-on.png') %>',
            starHalf: '<%= asset_path('star-half.png') %>',
            half: true,
            //I can't input just by reading
            readOnly: true,
            score: <%= note.rate %>,
          });
          </script>
        </td>
      </tr>
      <% end %>
      <% end %>
    </tbody>
  </table>
</div>
<div id="note-rate-<%= note.id %>"></div>
readOnly: true,
score: <%= note.rate %>,
This completes!
Please note that the explanation may be difficult to understand. Also, if there are any mistakes, I would appreciate it if you could teach me.
Recommended Posts