简体   繁体   中英

RoR voting system. Counting votes by condition vote = true or vote = false not working

I have these models

  • Issue
  • Vote

Issue has_many votes and Vote belongs_to issue. The Vote model has a boolean vote attribute. On the issues index view I want to cycle through the issues and display the title, body, an up vote button, a down vote button, and respective labels that show how many up votes and down votes there currently is. I do this with a form with hidden fields for issue_id and vote (1 or 0). Methods on the Issue model are supposed to count the votes. But I keep getting 0 returned. Totalvotes_count works but the other two don't. In the server log I see the votes being created with the proper issue_id and vote value but the queries aren't working for some reason.

Issue model

class Issue < ActiveRecord::Base
attr_accessible :body, :end_at, :title
validates_presence_of :title, :body, :end_at
has_many :votes

def upvotes_count
    votes.count(:conditions => "vote = 1")
end

def downvotes_count
    votes.count(:conditions => "vote = 0")
end

def totalvotes_count
    votes.count
end

end

index.html.erb

<% @issues.each do |issue| %>
<li>
    <div class="issue">
        <h2><%= issue.title %></h2>
        <p><%= issue.body %></p>

        <%= form_for(@vote, :remote => true) do |f| %>
        <%= f.hidden_field "issue_id", :value => issue.id %>
        <%= f.hidden_field "vote", :value => 1 %>
        <%= submit_tag issue.upvotes_count.to_s + " Up", :class => 'up-vote' %>
        <% end %>

        <%= form_for(@vote, :remote => true) do |f| %>
        <%= f.hidden_field "issue_id", :value => issue.id %>
        <%= f.hidden_field "vote", :value => 0 %>
       <%= submit_tag issue.downvotes_count.to_s + " Down", :class => 'down-vote' %>
        <% end %>

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

Votes Controller

class VotesController < ApplicationController

  def index
    @votes = Vote.find(:all, :include => :issue)
  end

  def new 
    @vote = Vote.new(params[:vote])

    respond_to do |format|
        format.html # new.html.erb
        format.xml  { render :xml => @vote }
    end
  end

  def create
    @vote = Vote.new(params[:vote])

    respond_to do |format|
      if @vote.save
          format.js
          format.html { redirect_to issues_path }
      else
          format.html { redirect_to issues_path }
      end
    end
  end

end

Issues controller (partial)

class IssuesController < ApplicationController
  # GET /issues
  # GET /issues.json
  def index
    @issues = Issue.all

    @vote = Vote.new


    respond_to do |format|
      format.html # index.html.erb
      format.json { render json: @issues }
    end

end

I believe your problem is that you do not have " self " called on your methods in the model, but as tamersalama mentioned this is likely overkill for simple vote tracking. It is probably just easiest to write a simple +1 method on an :upvote and :downvote attribute.

What is the default value of vote . If it's NULL - then neither would work.

Reading the question more carefully - it looks like the value in vote determine if it's an up or downvote. I suggest you'd use a STI (single-table inheritance) mechanism for Vote , where you'd create a type column to store the type of vote (either :upvote, :downvote), with an index on the type attribute.

All of this however seems like an overkill (depending on the rest of your domain). You could simply cache votes along with each of the issues. A column for upvote and one for downvote would suffice. Unless you'd want to track other attributes on Vote (like people who upvotes for example).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM