views:

168

answers:

2

I've a simple rating system setup in a blog model. I use a custom method to increase rating, which is integer in blog db.

def increase
  @post = Post.find(params[:id]).increment!(:rating)
  if logged_in?
    current_user.increment!(:votes)
  end
  flash[:notice] = "Thanks for rating"
  redirect_to posts_url
end

Right now, I can vote as many times as I want, which is of course a recipe for disaster. Users can vote multiple times and drive the count way way up.

How do I make it so that the vote submit button go away after submitting it once. I thought of making a separate model for rating and use a custom token, but seems needlessly complicated for a simple app.

Any help?

Senthil

A: 

You need to keep a list with users who votes on a particular subject/post. Or you need to keep a list attached to each user containing the posts the user voted on. Whether you store the information along with the posts or users is your choices and probably depends on your application requirements.

When displaying the page containing the vote button, you have to check whether the current_user already voted or not. And do not show the button if a vote was cast already. For safety reasons you might want to check also whether an user voted in the code you showed above in order to prevent voting without using the button.

If you also allow people who are not logged in to vote, you'd need to store their IP address or something.

Veger
+1  A: 

One way of doing this would be to have your Post model and a RatedPost model. The RatedPost model could contain info like incremented:boolean, decremented:boolean, changed_by:integer (user_id), post_id:integer.

You can then identify if RatedPost.find_by_post_id_and_changed_by(post.id, user.id) returns any records.

You can also identify if the points were incremented or decremented. Thus you can allow a user to change his vote for a certain period of time (say 24 hours).

Sid