Rails에서 「Raty」를 사용한 별 기능을 붙인다

편의점에서 부담없이 채취하는 고단백질을 관리하는 사이트를 만들 때
유저가 입소문 투고할 수 있는 기능을 작성, 별에 의한 평가 기능이 있으면 좋다고 생각했으므로 구현.
비슷한 기사는 다른 것도 있지만, slim으로 쓰여진 기사가 없었기 때문에 쓰기.

대상자, 환경



· Rails에서 "Raty"를 사용하여 별의 기능을 만들고 싶은 사람
· slim을 사용하고 있습니다.
· Rails 5.2.4

목표



・별 입력(0.5단위)
· 별 표시
・평균점 산출

참고 URL



이미지



전제



· User 모델
・Food 모델
· Review 모델

가 있다고 가정합니다. 테이블 상관도
이번에는 "rate"를 제외한 모든 것이 있다고 생각하십시오.

Food와 Review는 자신의 모델에 적합합니다 m (_ _) m

입력편 form로 표시하자



컬럼 추가


be rails g migration AddRateToReview rate:float
class AddRateToReview < ActiveRecord::Migration[5.2]
  def change
    add_column :reviews, :rate, :float, null: false, default: 0
    # floatにすることを推奨(小数点に対応できるため)。nullの制約は各自判断してください
  end
end

모델측은 하기. 1이상~5이하의 숫자는 기호로.

review.rb

  validates :rate, numericality: {
    less_than_or_equal_to: 5,
    greater_than_or_equal_to: 1
  }, presence: true

이미지를 외부에서 저장



이 Github에서 이미지를 assets/images 아래에 저장합니다.



js의 코드 복사



이 Github에서 코드를 복사하여 jquery_raty.js 등의 적절한 이름을 흔들어,applicaiton.js 부터 require

view에 추가



스트롱 파라미터에 추가 등한 후, (i18n화도 하고 있습니다)
#star.form-group
   = f.label :rate
   = f.hidden_field :rate, id: :review_star
  #star がポイントです(jsを呼ぶ)

같은 view 파일 내에서
javascript:
 $('#star').raty({
   size: 36,
   starOff: "#{asset_path('star-off.png')}",
   starOn: "#{asset_path('star-on.png')}",
   starHalf: "#{asset_path('star-half.png')}",
   scoreName: 'review[rate]', # reviewカラムに保存するので忘れないように
   half: true, # ★の半分の入力を行う
 });
# ダブルクオーテーションで囲みましょう

여기까지 입력하면 아래와 같이 표시가 되어 있을 것. 실제로 저장하거나 DB를 확인하는 것도 잊지 마세요!
만약 표시되어 있지 않다면, 디버그 해 확인합시다.


표시편 each로 돌자



다음은 DB에 저장된 숫자를 뷰에 묘사합니다.

_review.html.slim으로 돌리기



each로 돌리는 것을 전제로 이야기를 진행합니다.

id="star-rate-#{review.id}"

처럼 쓰면 id를 동적으로 할 수 있습니다.

표시편 평균점을 내자



마지막으로 덤으로 검토 평균 점수를 내고 싶습니다.

review는 음식 모델에 붙어 있으며 음식이 여러 리뷰를 가지고 있다는 관계입니다. (자세한 것은 최초의 참고 자료를 봐 주세요)

끈이 붙은 것을 average 등으로 좋은 느낌으로 해주면, 이런 느낌으로 표시 할 수 있어야합니다!

_food.html.slim
.col-md-3.col-sm-4.col-xs-12.text-center#food_parts
  food[id="#{food.id}"]
  = link_to image_tag(food.decorate.image_url, width: 220, height: 220, class: 'food_parts_image'),food_path(food)
  .card-body
    h5
      = link_to food.name, food_path(food)
    ul.text-left
      li 税込#{food.price}li #{food.protein}g
      li #{food.brand.pluck(:name).first}
      li id="star-rate-#{food.id}" 口コミ#{food.reviews.count} &nbsp;
//注目ポイント ↑
    == render 'likes/likes_basic', food: food #いいね機能です、無視してください
//星評価
javascript:
  $('#star-rate-#{food.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: "#{food.reviews.average(:rate).to_f.round(1)}",
    //注目ポイント↑ 平均点を算出し、round関数で切り上げ
  });
//星評価終わり


이런 느낌으로 표시할 수 있을 것! (덧붙여서, 추천 샐러드 치킨은 파미마입니다)
(이미지의 별에서는, 리뷰 2건으로 「4」와 「2」의 평가가 붙어 있습니다.


더러워진 코드는 부분적으로



현재의 view는 js가 쓴 글이 되어 있다고 생각합니다.shared/_star 등을 만들어 js만 부분으로 합시다! 렛츠 리팩토! 😉

_star.html.slim
/ 星評価 review_formからrender(newとeditで使用中)
javascript:
  $('#star').raty({
    size: 36,
    starOff: "#{asset_path('star-off.png')}",
    starOn: "#{asset_path('star-on.png')}",
    starHalf: "#{asset_path('star-half.png')}",
    scoreName: 'review[rate]',
    half: true,
  });

/ 星平均 _foodからrender
- if food.present? #自分の仕様上必要なif文
  javascript:
    $('#star-rate-#{food.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: "#{food.reviews.average(:rate).to_f.round(1)}",
      // 平均点を算出し、round関数で切り上げ
    });


이것으로 상당히 깨끗했다고 생각합니다.

요약



구현 초기, js 파일에 필사적으로 '#{asset_path('star-off.png)}', 와 같이 asset_path 를 쓰고 있었습니다만, 불리지 않고 빠졌습니다.

냉정하게 생각하면, js와 Ruby로 생성되는 타이밍이 다르므로, js 파일에 asset_path를 써도 움직이지 않네요(라는 인식입니다). gon 라는 gem을 사용하면 어떻게든,, 같지만, 시도하지는 않습니다.

gon을 사용한 Rails와 Javascript의 연계에 대해

별기능을 구현하려면 raty나 rate.yo등이 있습니다만, 알면 비교적 간단한 raty는 추천입니다.
별, 긴장이 올거야 😊

좋은 웹페이지 즐겨찾기