Reputation: 635
I currently have a comment controller that has the method vote_up and vote_down this is how my vote_up currently works.
My Comment model has description and a count field.
def vote_up
@comment = Comment.find(params[:comment_id])
@comment.count += 1
if @comment.save
flash[:notice] = "Thank you for voting"
respond_to do |format|
format.html { redirect_to show_question_path(@comment.question) }
format.js
end
else
flash[:notice] = "Error Voting Please Try Again"
redirect_to show_question_path(@comment.question)
end
end
This allows for multiple vote up and downs. How would I design it so that a user can only vote once per comment but somehow keep track if they voted up or down, so they have the ability to change their vote if they want too.
Upvotes: 5
Views: 2190
Reputation: 4043
You could do something like this. It prohibits identical votes but allows changing the vote to the opposite (it's a thumbs up/thumbs down system).
def vote(value, user) # this goes to your model
#find vote for this instance by the given user OR create a new one
vote = votes.where(:user_id => user).first || votes.build(:user_id => user)
if value == :for
vote_value = 1
elsif value == :against
vote_value = -1
end
if vote.value != vote_value
vote.value = vote_value
vote.save
end
end
migration:
def self.up
create_table :votes do |t|
t.references :comment, :null => false
t.references :user, :null => false
t.integer :value, :null => false
end
add_index :votes, :post_id
add_index :votes, :user_id
add_index :votes, [:post_id, :user_id], :unique => true
end
Alternatively, you could use a gem called thumbs_up
or any other.
Upvotes: 3
Reputation: 15530
class AnswersController < ApplicationsController
def vote
#params[:answer_id][:vote]
#it can be "1" or "-1"
@answer = Answer.find(params[:answer_id])
@answer.vote!(params[:answer_id][:vote])
end
def show
@answer = Answer.find(params[:answer_id])
@answer.votes.total_sum
end
end
class Answer < ActiveRecord::Base
has_many :votes do
def total_sum
votes.sum(:vote)
end
end
def vote!(t)
self.votes.create(:vote => t.to_i)
end
end
class Vote < ActiveRecord::Base
belongs_to :answer
belongs_to :user
validates_uniqueness_of :user_id, :scope => :answer_id
end
Upvotes: 2
Reputation: 34613
you could perhaps add a validation in your model to make sure that count is numerically equal to or less than 1
validates :count, :numericality => { :less_than_or_equal_to => 1 }
Upvotes: 1