Creating Unique Votes

I have a rails app that uses voting. Right now I have it set up so that you can vote on a word, but it doesn't limit the number of votes. So someone can vote on the same word more than once.

How do I make it so that you can only vote once on a word. Some methods I've found online included checking for a unique ip address but that can bring problems for people at work or places with block ip addresses.

I was thinking that I would have to using session cookies or something like that. But I'm new to RoR and don't know where to start.

Here is my current code:

# CONTROLLER class VotesController < ApplicationController

  def create   @word = Word.find(params[:word_id])   @word.votes.create(:user => @current_user)

  respond_to do |format|     format.html { redirect_to @word }     format.js   end

  end

end

# MODEL class Vote < ActiveRecord::Base   belongs_to :word, :counter_cache => true   belongs_to :user end

# VIEWS

# Create.js.rs page.replace_html 'vote_score', "Score: #{@word.reload.votes.size}" page[:vote_score].visual_effect :highlight, :duration => 2.0 page[:vote_score].visual_effect :pulsate, :duration => 1.5, :collection => @word.votes.latest

#Edit.rjs page.replace_html 'vote_score', "Score: #{@word.votes.size}" page[:vote_score].visual_effect :highlight, :duration => 2.0 page[:vote_score].visual_effect :pulsate, :duration => 1.5

#Vote.html.erb <li><%= vote.created_at.to_formatted_s(:short) %></li>

I would appreciate some help with figuring this out.

Thanks in advance.

I think that you want to build in an authentication system first (restful_authentication) so that you can reliably identify who the user is. After that it is a simple matter of logging a record in a table that identifies that a user has voted on a specific word. So always check beforehand if a user has voted on a word and then disallow repeated voting. People move around and identifying a user using just the IP address alone is not sufficient in my opinion. Hope this helps. Regards, Bharat

Could you tell me what code I should write. I'm really new to RoR and have no idea how to do that.

I can point you in the right direction, I hope. You want to learn basics of Rails first. An excellent starter book would be Patrick Lenz's Simply Rails 2. After that, I would to a google search on restful_authentication tutorials. There are a lot of good tutorials available. Then you would be in a much better position to address the problem at hand.

You should also keep in mind that most ISPs use dynamically assigned IP addresses that can change at any time for the same user.

I agree that you must be able to identify the person. Cookies are insufficient. They can be easily cleared by the user. I use Safari, most of the time, and I reset it often which quickly and conveniently clears all cookies.

As another option you could track people by using OpenID if you don't want to take on the hassles of usernames and passwords. This is what stackoverflow.com is doing.

I think OpenID a great idea. But, there is a trade-off there. Setting up an OpenID initially adds even more complication to the end user than a username and password. The difference is that it's a one-time complication. The benefit to the end user is that they don't have to remember 20 passwords for 20 sites. So they will be able to use their OpenID on many other sites that support it. And for current OpenID users it involves much less complication. They only need to enter their OpenID URL and that's it. All you have to do is validate their OpenID.

There's a nice OpenID gem "ruby-openid" that should make implement it fairly painless.

Bharat Ruparel wrote:

Actually I have the Simply Rails 2 book and the Restful_Authentication plugin installed on my app in addition to the open-id.

The problem is adding the unique voting. I'll take a look at adding an extra field.

OK. If you are that far along. Then you may want to create a votes table something similar to as I show below:

votes:

id - int - created by rails in migrations question_id, even_id, ... whatever you are trying to track a user vote on user_id - foreign key from your users table voted_on - if you want to explicitly record the time and date

Note that you may or may not want to create voted on explicitly since if you are using Rails 2.1.0, it will automatically create created_at, and updated_at giving you the same functionality (more since you have updated_at field too).

Before saving a user's vote, you want to check in this table (write a validation function in the controller using before_filter) if the user has already voted on this question (or event or whatever you are tracking). If you find an existing record then simply display a flash message and return false.

I cannot write the code for you, but here is one approach to solving this problem. Give it a try.

Bharat