Search code examples
ruby-on-railssessionvoting

Rails vote per IP address per limit 1 per day


I have a Ruby on Rails 3.2 application where users are able to upload videos directly to youtube with the Youtube_it Rails gem. After the video is uploaded, the people are able to vote on the videos. I have it setup now where anyone can vote on the videos and they don't have to register(using devise) to vote on the videos.

I would like to limit the votes to 1 vote per day per IP address. If a person has voted from an IP address, they should not be able to vote again for 24 hours.

I'm new to rails and I can't seem to figure out how to implement this. I think I would have to create a model to store the users IP address in it with request.remote_ip. How would I limit their voting to once per day?

My routes.rb

resources :videos do
 collection do
  put '/vote_up/:id' => "videos#vote_up", :as => :vote_up
 end
 new do
  post :upload
  get  :save_video
 end
end

My videos show view

 <%= link_to vote_up_videos_url(@video.id), class: "btn btn-main", :method => :put do %>
   <i class="fa fa-thumbs-up"></i> Upvote this video
 <% end %>

Videos controller

def vote_up
 @video = Video.find(params[:id])
 @video.update_attribute(:votes_up, (@video.votes_up.to_i + 1))
 redirect_to @video
end

Solution

  • # in controller
    def vote_up
     video = Video.find(params[:id])
     video.vote!(request.ip)
    
     redirect_to video
    end
    
    # in video model
    def vote!(ip)
      unless Vote.recent.exists?(:ip => ip, :video_id => id)
        increment!(:votes_up) 
        Vote.create(:ip => ip, :video_id => id)
      end
    end
    
    # in vote model
    class Vote < ActiveRecord::Base
      scope :recent, -> { where("created_at > ?", 24.hours.ago) }
    end
    
    # migration
    class CreateVotes < ActiveRecord::Migration
      def change
        create_table :votes do |t|
          t.integer :video_id
          t.string  :ip
        end
        add_index :votes, :video_id, :ip
      end
    end