Rails コメント＋星機能

皆さんこんにちわ！！

今日もプログラミングしていますか？:point_up:

今回は詳細ページにコメント星機能をつけていく機能を紹介します！！

注意：大前提としていいね機能を実装していないと実装できません！！:sunny:

![スクリーンショット (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738887/35e479f8-8aed-90ec-d256-c50979d5b2ae.png)




<br>
<dt>Step1:星機能（詳細ページ用）の中間テーブルとアソシエーションを組む！！！</dt>

```ruby:.ターミナル
rails g model Review eve:integer content:string user:references tweet:references

rails db:migrate
```

<dt>Step2:userとtweetのモデルにアソシエーションの情報を打ち込む！！！</dt>

```ruby:app/models/user.rb
has_many :reviews, dependent: :destroy
```

```ruby:app/models/tweet.rb
has_many :reviews, dependent: :destroy
```

<br>

<dt>Step3:コントローラーの作成！！</dt>

```ruby:ターミナル
rails g controller reviews
```

```ruby:app/controllers/reviews_controller.rb
class ReviewsController < ApplicationController
  before_action :authenticate_user!

  def create
    @tweet = Tweet.find(params[:tweet_id])
    review = @tweet.reviews.build(review_params) 
    review.user_id = current_user.id
    if review.save
      flash[:success] = "コメントしました"
      redirect_back(fallback_location: root_path)
    else
      flash[:success] = "コメントできませんでした"
      redirect_back(fallback_location: root_path)
    end
  end

  private

    def review_params
      params.require(:review).permit(:eve, :content)
    end
end
```

```ruby:app/controllers/tweets_controller.rb
def show
        @tweet = Tweet.find(params[:id])
# 追記ここから
        @reviews = @tweet.reviews
        @review = Review.new
# 追記ここまで
    end
```
helperの編集
```ruby:app/helper/tweets_helper.rb
module TweetsHelper

      def getPercent(number) 
          if number.present?
            calPercent = number/5.to_f * 100
            # calPercent = number/10.to_f * 100
            #↑１０段階評価の際は2行目コメントアウトを外して、1行目をコメントアウト。
            percent = calPercent.round
            #↑CSSは小数が含まれると、widthの幅を指定できないので四捨五入して整数化。
            return percent.to_s
          else
            return 0
          end
        end
end
```

<br>
<dt>Step4:ルーティング更新！！</dt>

```ruby:routes.rb
Rails.application.routes.draw do
   resources :tweets do
    resources :likes, only: [:create, :destroy]
#追記箇所
    resources :reviews, only: [:create]
# ここまで
   end
end
```
<br>
<dt>Step5:ViewとCSSの追加・更新！！</dt>


```ruby:app/views/tweets/show.html.erb
# 割愛

# 追記ここから
<div class="review-wrapper">
  <p>一覧</p>
  <% @reviews.each do |c| %>
    <div>
      <%= c.user.email unless c.user.blank? %>
      <br>
      <div>
<h2>口コメ：
<span class="star-rating">
   <span class="star-rating-front" style="width: <%= getPercent(c.eve) %>%;">★★★★★</span>
   <span class="star-rating-back">★★★★★</span>
</span> 
</h2>
<%= c.content %>
</div>
   
      <br>
  <% end %>

  <% if user_signed_in? %>
    <%= form_with(model: [@tweet, @review], local: true) do |f| %>
      <h5>評価基準</h5>
  <div class="post_form">
    <%= f.radio_button :eve,  5 ,id: 'star6'%>
    <label for="star6"><span class="text">Great</span>★</label>

    <%= f.radio_button :eve,  4 ,id: 'star7'%>
    <label for="star7"><span class="text">good</span>★</label>

    <%= f.radio_button :eve, 3 ,id: 'star8'%>
    <label for="star8"><span class="text">normal</span>★</label>

    <%= f.radio_button :eve, 2 ,id: 'star9'%>
    <label for="star9"><span class="text">but</span>★</label>

    <%= f.radio_button :eve, 1 ,id: 'star10'%>
    <label for="star10"><span class="text">worse</span>★</label>
 </div>
     <%= f.text_area :content %>
      <%= button_tag type: "submit" do %>
        <i class="far fa-reviews"></i> 評価する
      <% end %>
    <% end %>
  <% end %>
</div>
#追記ここまで
```
```ruby:review.scss
/*　以下詳細ページの星用のCSS　*/

.star-rating {
    position: relative;
    display: inline-block;
    width: 5em;
    height: 1em;
    font-size: 25px;
  }
  .star-rating-front {
    display: inline-block;
    position: absolute;
    top: 0;
    left: 0;
    overflow: hidden;
    color: #ffcc33;
  }
  .star-rating-back {
    display: inline-block;
    color: #ccc;

  }
  .post_form{
    display: flex;
    flex-direction: row-reverse;
    justify-content: flex-end;
  }
  .post_form input[type='radio']{
    display: none;
  }
  .post_form label{
    position: relative;
    padding: 10px 10px 0;
    color: gray;
    cursor: pointer;
    font-size: 30px; /*星の大きさを変更するときはここ*/
  }
  .post_form label .text{
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    text-align: center;
    font-size: 9px; /*星の上の説明書きの大きさを変更するときはここ*/
    color: gray;
  }
  .post_form label:hover,
  .post_form label:hover ~ label,
  .post_form input[type='radio']:checked ~ label{
    color: #ffcc00;
  }
```

<br>






<dt>Step6:確認！！</dt>
上記の写真のようになれば完了です！！！
<br>
以上になります！！！
いろんな機能実装していこう！！！

追加：もしユーザーが一度のみしか投稿させない場合

```ruby:review.rb
class Review < ApplicationRecord
    
    belongs_to :user
#追加部分
    validates :user_id, uniqueness: { scope: :register_id }
#ここまで
end
```