Error voting response in model with polymorphism

0

I have the following model that allows you to vote for questions and for answers with the model Vote defined as a polymorphic model.

The question vote part works well for me but I do not know how to approach the voting for the answers.

The answers depend on a question, and the question voting part works well for me. How can I implement the question voting in show view?

vote.rb

# == Schema Information
#
# Table name: votes
#
#  id            :integer          not null, primary key
#  voteable_id   :integer
#  voteable_type :string
#  created_at    :datetime         not null
#  updated_at    :datetime         not null
#  user_id       :integer
#

class Vote < ApplicationRecord
  belongs_to :voteable, polymorphic: true
  belongs_to :user

  def  self.voted_by?(user, voteable)
    voteable.votes.find_by(user_id: user.id)
  end
end

routes.rb

Rails.application.routes.draw do
  devise_for :users
  resources :comments

  resources :questions do
    resources :answers, except: [:show] do
      resources :comments, except: [:show], module: :answers
      resources :votes, only:[:create,:update, :destroy], module: :answers
    end
    resources :votes, only:[:create,:update, :destroy], module: :questions
    resources :comments, except: [:show], module: :questions
  end

  root 'questions#index'
end

View show.html.erb of the model Question where all the information related to questions , answers and votes is displayed and where I must make an implementation similar to what what do I do with votes of questions .

<div class="container">
    <div class="row">
        <div class="col-sm-8 col-sm-offset-1">
            <h2 class="title-question"><%= @question.title %></h2>
        </div>
    </div>
    <div class="questions">
        <% if user_signed_in? %>
        <div class="row">
              <div class="col-sm-1 col-sm-offset-1">
                    <% vote = Vote.voted_by?(current_user,  @question) %>
                <% if vote %>
                      <%= link_to question_vote_path(@question, vote), method: :delete, class: "question-upvote upvote-active" do %>
                          <span class="upvote-arrow"></span>
                          <span class="upvote-count"><%= @question.votes.count %></span>
                      <% end %>
                <% else %>
                    <%= link_to question_votes_path(@question), method: :post, class: "question-upvote" do %>
                            <span class="upvote-arrow"></span>
                        <span class="upvote-count"><%= @question.votes.count %></span>
                    <% end %>
                <% end %>
                </div>
                <div class="col-sm-8 body-show-question">
                    <span> <%= markdown(@question.body) %> </span>
                    <span class="comments">
                        <%= render partial: "comments/comments", locals: {commentable: @question} %>
                    </span>
                    <%= render partial: "comments/form", locals: {commentable: [@question]} %>
                </div>
            </div>
            <div class="row">
                <div class="col-sm-8 col-sm-offset-1">
                    <div>
                        <h2>(<%= @question.answers.count %>) Respuesta(s)</h2>
                    </div>

                    <% @question.answers.each do |answer|  %>
                    <div class="row">
                      <div class="col-sm-1 col-sm-offset-1">
                            <% vote = Vote.voted_by?(current_user, answer) %>
                        <% if vote %>
                              <%= link_to question_answer_vote_path(@question, answer), method: :delete, class: "question-upvote upvote-active" do %>
                                  <span class="upvote-arrow"></span>
                                  <span class="upvote-count"><%=answer.votes.count %></span>
                              <% end %>
                        <% else %>
                            <%= link_to question_answer_votes_path(@question, answer, vote), method: :post, class: "question-upvote" do %>
                                    <span class="upvote-arrow"></span>
                            <% end %>
                        <% end %>
                        </div>

                    <div class="body-answer">
                            <span> <%= markdown(answer.body) %> </span>
                                <%= render partial: "comments/comments", locals: {commentable: answer} %>
                        </div>
                        <div class="form-comments-answer">
                            <span>
                                <%= render partial: "comments/form", locals: {commentable: [answer.question, answer]} %>
                            </span>
                        </div>
                    <% end %>
                </div>
            </div>
            <div class="row">
                <div class="col-sm-8 col-sm-offset-1">
                    <%= render partial: "answers/form", locals: {question: @question} %>
                </div>
            </div>
        <% else %>
            <div class="row">
                <div class="col-sm-1 col-sm-offset-1">
                    <div class="question-upvote">
                        <span class="upvote-arrow"></span>
                        <span class="upvote-count"><%= @question.votes.count %></span>
                    </div>
              </div>
            <div class="col-sm-8 body-show-question">
                <span> <%= markdown(@question.body) %> </span>
                <span class="comments">
                    <%= render partial: "comments/comments", locals: {commentable: @question} %>
                </span>
            </div>
        </div>
        <div class="row">
            <div class="col-sm-8 col-sm-offset-1">
                <div>
                    <h2>(<%= @question.answers.count %>) Respuesta(s)</h2>
                </div>
                <% @question.answers.each do |answer|  %>
                    <div class="body-answer">
                        <span> <%= markdown(answer.body) %> </span>
                        <%= render partial: "comments/comments", locals: {commentable: answer} %>
                    </div>
                <% end %>
            </div>
        </div>
    </div>
    <% end %>
</div>

votes_controller.rb

class VotesController < ApplicationController
  before_action :authenticate_user!
  before_action :set_voteable, only: [:show, :edit, :update, :destroy]

  def create
    @voteable.votes.create(user: current_user)
    redirect_to question_path(@voteable), notice: "A successfully voted for the question..."
  end

  def destroy
    @voteable.votes.where(user: current_user).take.try(:destroy)
    redirect_to question_path(@voteable), notice: "Successfully removed question vote"
  end
end
    
asked by García Henry 27.10.2017 в 02:47
source

1 answer

1

The main problem is in the helpers of routes used to apply / delete the votes of the answers; in your code you have question_vote_path and question_votes_path , which point to questions only, but you need them to point to the answers to the question, then you must use question_answer_vote_path and question_answer_votes_path to make it work.

<!-- app/views/questions/show.html.erb (código parcial) -->

<% if vote %>
  <%= link_to question_answer_vote_path(@question, answer), method: :delete, class: "question-upvote upvote-active" do %>
      <span class="upvote-arrow"></span>
      <span class="upvote-count"><%=answer.votes.count %></span>
  <% end %>
<% else %>
    <%= link_to question_answer_votes_path(@question, answer, vote), method: :post, class: "question-upvote" do %>
        <span class="upvote-arrow"></span>
    <% end %>
<% end %>

It is important to note how I added @question to each route in order to identify the question to which it refers and thus have the complete route parameters.

Once this change has been made, you must update the VotesController driver so that, as in CommentsController you can obtain the id of the question through the variable @votable , regardless if this is an object Question or one Answer :

# app/controllers/votes_controller.rb:

class VotesController < ApplicationController
  before_action :authenticate_user!
  before_action :set_voteable, only: [:show, :edit, :update, :destroy]

  def create
    @voteable.votes.create(user: current_user)
    redirect_to question_path(question), notice: "A successfully voted for the question..."
  end

  def destroy
    @voteable.votes.where(user: current_user).take.try(:destroy)
    redirect_to question_path(question), notice: "Successfully removed vote"
  end

  private

    def question
      @voteable.try(:question) || @voteable
    end
end
    
answered by 28.10.2017 / 19:31
source