Estoy creando una aplicación de encuesta. Los usuarios pueden votar, pero si ya han votado, no pueden volver a votar.

Este es el método vot_for que lo verifica:

User.rb

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

has_many :votes, dependent: :destroy
has_many :vote_options, through: :votes

def voted_for?(poll)
  vote_options.any? {|v| v.poll == poll }
end
end

Esto funciona en mi formulario de votación:

Polls / _voting_form.html.erb

<%= form_tag votes_path, method: :post, remote: true, id: 'voting_form' do %>
  <%= hidden_field_tag 'poll[id]', @poll.id %>

  <%= render partial: 'polls/vote_option', collection: @poll.vote_options, as: :option %>

  <% if current_user.voted_for?(@poll) %>
    <p>You have already voted!</p>
  <% else %>
    <%= submit_tag 'Vote', class: 'btn btn-lg btn-primary' %>
  <% end %>
<% end %>

Ahora también quiero hacer lo mismo en la página de índice, que muestra la lista de encuestas y un botón VOTAR para cada una. Quiero mostrar un botón VER si el usuario ya votó esa encuesta.

Polls / index.html.erb

        <div class="container">

<% content_for(:page_header) {"POLLS"} %>

  <%= render "filter_box" %>

  <% @polls.each do |poll| %>

    <div class="well">

      <div class="row">
        <h4><%= poll.question %>
          <small>(voted:
            <%= poll.votes_summary %>)</small>
        </h4>
      </div>

      <div class="row">
        <div class="col-sm-2"><%= 'OPEN' %>
          <p><%= poll.open_date %></p>
        </div>
        <div class="col-sm-2"><%= 'CLOSE' %>
          <p><%= poll.close_date %></p>
        </div>
        <div class="col-sm-2"><%= 'DIVISION' %>
          <p><%= poll.division.try(:name) %></p>
        </div>
        <div class="col-sm-2">
          <p>
            <% if  current_user.voted_for?(@poll) %>
              <%= link_to 'VIEW', poll_path(poll), class: 'btn btn-primary btn-lg block' %>

            <% else %>
                <%= link_to 'VOTE', poll_path(poll), class: 'btn btn-primary btn-lg block' %>
            <% end %>
          </p>
        </div>

        <div class="col-sm-3">
          <div class="btn-group">

            <%= link_to 'Edit', edit_poll_path(poll), class: 'btn btn-default' %>
            <%= link_to 'Delete', poll_path(poll), method: :delete, class: 'btn btn-danger', data: {confirm: 'Are you sure?'} %>

          </div>

        </div>

      </div>
        </div>
    <% end %>

Polls_controller

class PollsController < ApplicationController

  before_action :authenticate_user!

  def index
    @q = Poll.ransack(params[:q])
  @polls = @q.result.order('id ASC')
    respond_to do |format|
      format.html
  end
  end


  def new
    @poll = Poll.new
      @poll.vote_options.build
  end

  def create
      @poll = Poll.new(poll_params)
      if @poll.save
        flash[:success] = 'Poll was created!'
        redirect_to polls_path
      else
        render 'new'
      end
    end

  def edit
  @poll = Poll.find_by_id(params[:id])
end

def update
  @poll = Poll.find_by_id(params[:id])
  if @poll.update_attributes(poll_params)
    flash[:success] = 'Poll was updated!'
    redirect_to polls_path
  else
    render 'edit'
  end
end

def destroy
  @poll = Poll.find_by_id(params[:id])
  if @poll.destroy
    flash[:success] = 'Poll was destroyed!'
  else
    flash[:warning] = 'Error destroying poll...'
  end
  redirect_to polls_path
end

def show
  @poll = Poll.includes(:vote_options).find_by_id(params[:id])
  @vote = Vote.find_by_id(params[:id])

end

  private

  def poll_params
    params.require(:poll).permit(:question, :description, :division_id, :open_date, :close_date, vote_options_attributes: [:id, :title, :_destroy])
  end
end

Pero si uso esto, ignora la primera condición y muestra el botón VOTE para todos. Incluso las encuestas ya voté.

¿Cómo puedo solucionarlo?

0
Mirco Cattabriga 13 nov. 2017 a las 07:53

2 respuestas

La mejor respuesta

@poll no es una variable definida y será nula cuando se use en la instrucción if.

Tienes la variable poll. Entonces use la variable poll en la instrucción if en index.html.erb en lugar de @poll.

1
Aakash Gupta 13 nov. 2017 a las 06:40

No publicó las acciones de su controlador, pero probablemente no esté asignando @poll en su acción de índice. Probablemente tengas algo similar a @polls asignado en su lugar. En cuyo caso, deberá iterar sobre @polls en su vista y ejecutar su lógica condicional en cada miembro de esa colección.

1
OutlawAndy 13 nov. 2017 a las 05:08