SitePoint Sponsor

User Tag List

Results 1 to 6 of 6

Hybrid View

  1. #1
    SitePoint Member
    Join Date
    Mar 2007
    Posts
    2
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Question Voting Only Once

    Hello all - I'm wondering about making a change to the Shovell application to preclude the same user from voting multiple times for the same story. Should be straight forward, but where/how to do it? (That's the problem with book-learning: the knowledge stops at the end of the book!)

    I'm thinking this might be accomplished by changing the relations for the User class. Would something like this make sense?

    Code:
    class User < ActiveRecord::Base
    has_many :stories has_one :votes
    :through => :votes, :source => :story
    has_many :stories_voted_on,
    :through => :votes, :source => :story
    end
    I haven't tested this, but making a SWAG based on how this reads.

    Anyone try to do this already?

    Thanks

  2. #2
    SitePoint Evangelist
    Join Date
    Feb 2006
    Location
    Worcs. UK
    Posts
    404
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    What you need to do is carry out validation when a new vote is added. Have a look at the rails api description of validation:

    http://api.rubyonrails.com/classes/A...lidations.html

    So add a validation test to the vote model that checks whether a vote already exists for this user.

    I don't have a copy of "the Book", but if it matches common usage there will be a field in votes called user_id. In which case simply adding:
    Code:
    validates_uniqueness_of :user_id
    To the Vote model will do what you want.

  3. #3
    SitePoint Member
    Join Date
    Dec 2008
    Posts
    2
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I was hoping to resurrect this thread. The suggestion above doesn't really seem to help.

    Perhaps it's possible to limit the voting by checking if the user has already voted on a particular story previously.

    Unfortunately I am being blocked from submitting the controller and model code. If anyone else could do this it may help.

    In any case any suggestions how to limit the voting would be greatly appreciated.

  4. #4
    SitePoint Addict
    Join Date
    Feb 2007
    Posts
    270
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Instead of the changes mentioned above, leave the code as is (user has many stories and has many votes, because you only want to keep a user from voting twice for the same story, not from voting for two different stories) and instead create a validation that fails when the vote by that user for that story is found to exist.

    An alternative, which I'd prefer as a user, is to use a filter to check and see if the particular vote already exists (vote with that user_id and story_id) and if it does, edit it rather than create a new one.

  5. #5
    Programming Team silver trophybronze trophy
    Mittineague's Avatar
    Join Date
    Jul 2005
    Location
    West Springfield, Massachusetts
    Posts
    16,454
    Mentioned
    160 Post(s)
    Tagged
    1 Thread(s)
    Many years of procedural coding and not using frameworks make it somewhat difficult for me to expand any knowledge I may have learned in RoR tutorials to implementing "original" ideas. So I am interested in understanding how to go about making this modification to the shovell application. The db schema has
    Code Ruby:
      create_table "votes", :force => true do |t|
        t.integer  "story_id"
        t.datetime "created_at"
        t.datetime "updated_at"
        t.integer  "user_id"
      end
    so there must be a way to use story_id and user_id to make sure there's only one entry where the user_id/story_id pair are unique.

    Is adding another before_filter in the VotesControlller the way? Or would a conditional in the create be the way to do it?
    Code Ruby:
    class VotesController < ApplicationController
     
      before_filter :login_required
     
      def create
        @story = Story.find(params[:story_id])
        @story.votes.create(:user => @current_user)
     
        respond_to do |format|
          format.html { redirect_to @story }
          format.js
        end
      end
     
    end

  6. #6
    SitePoint Member
    Join Date
    Jan 2009
    Posts
    5
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    From a user perspective, you shouldn't even display an option for a user to vote if they have already voted on a story. Having a validation run before_save is a good way to make sure it doesn't happen, but the user shouldn't get to that point in the first place.

    So, add a method to the User model (or alternatively, the Story model)

    Code:
    def has_voted?(story_id)
      # check to see if the user has voted on the story
      # something like
      !self.votes.find_by_story_id(story_id).nil?
    end
    which will return true if the user has voted on story_id.

    Then, create a helper method for your voting display

    Code:
    def show_vote(story,user)
      [... code that display a voting link ...] unless user.has_voted?(story.id)
    end
    Code isn't tested, but it should give the gist of what I'm getting at.
    Adrian
    Need help on your next project? Hire me


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •