LoginSignup
0
0

More than 1 year has passed since last update.

星レビュー機能の実装

Posted at

星レビュー機能の実装をしてみました。
ルーティングのネストを理解していれば、そこまで複雑ではありません。
ただ、form_withによるデータの流れがわからなかったので苦戦しました。

fontawsomeの導入が必要ですが、その方法は割愛します。

では、みていきましょう。今回はyoutube動画を参考にさせていただきました。

まずはルーティングです。
今回は誰かの投稿に対して、星5つで評価できるように実装しました。

routes.rb
 resources :posts do
    resource :reviews, only:%i[create]
 end

以下のルーティングができました。
色々な投稿の中のどの投稿にレビューするか可能になります。

 rails routes | grep reviews
post_reviews POST   /posts/:post_id/reviews(.:format)                                                                 reviews#create

今回は、form_withに最も苦戦しました!
正しいかわからないのですが、個人的な解釈を書いておきたいと思います。

views/posts/show.html.erb
<%= form_with model:@review, url:post_reviews_path(@post), local: true do |f| %>
 <div class="main-rating">
      <div class="ratings">
        <span class="fa fa-star-o" id="star"></span>
        <span class="fa fa-star-o" id="star"></span>
        <span class="fa fa-star-o" id="star"></span>
        <span class="fa fa-star-o" id="star"></span>
        <span class="fa fa-star-o" id="star"></span>
      </div>
      <div class="rating-value-display"><span id="rating-value-display">0</span>/5</div>
    </div>
<%= f.hidden_field :score, id:"rating_value" %>
<%= f.text_area :content %>
<%= f.submit "評価"%>
<% end %>
<%= javascript_pack_tag 'review_stars' %>

url:post_reviews_path(@post)

formのデータをどこに飛ばすかを示しています。
この場合は、reviewsコントローラーのcreateアクションに飛ばします。
その時にpost_idのデータが必要なので、@postを渡しています。
これは正確には@post.idだったはず。

@postについては、postsコントローラーのshowアクションに
@post = Post.find(params[:id]) を記述しておく。

@review

reviewsコントローラーに飛んだ際に、どのモデルを参照するか示しています。
今回は、新たにデータを保存していきます。

def create
    @review = Review.new(review_params)
end

  private
  def review_params
    params.permit(:post_id, :score, :content)
  end
app/javascript/packs/review_stars.js
const stars = document.querySelector(".ratings").children;
const ratingValue = document.querySelector("#rating_value");
const ratingValueDisplay = document.querySelector("#rating-value-display");


let index;

for(let i=0; i < stars.length; i++){
  stars[i].addEventListener("mouseover", () => {
  for(let j=0; j<stars.length; j++){
  stars[j].classList.remove("fa-star")
  stars[j].classList.add("fa-star-o")
  }
  for(let j=0; j<=i; j++){
    stars[j].classList.remove("fa-star-o");
    stars[j].classList.add("fa-star");
  }
  })

  stars[i].addEventListener("click", () => {
    ratingValue.value = i+1;
    ratingValueDisplay.textContent = ratingValue.value;

    index = i;
  })

  stars[i].addEventListener("mouseout", () => {
    for(let j=0; j<stars.length; j++){
      stars[i].classList.remove("fa-star");
      stars[i].classList.add("fa-star-o");
    }
    for(let j=0; j <=index; j++){
      stars[j].classList.remove("fa-star-o");
      stars[j].classList.add("fa-star");
    }
  })
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0