106 lines
2.3 KiB
Ruby
106 lines
2.3 KiB
Ruby
class Vote < ActiveRecord::Base
|
|
belongs_to :photo
|
|
belongs_to :user
|
|
|
|
validate :unique_for_user
|
|
validates_presence_of :photo_id
|
|
|
|
attr_protected :user_id
|
|
attr_protected :session_id
|
|
|
|
after_create :update_photo_stats
|
|
after_destroy :update_photo_stats
|
|
|
|
##
|
|
# Checks if this vote is anonymous, or not an authenticated User vote.
|
|
#
|
|
def anonymous?
|
|
self.user_id.nil?
|
|
end
|
|
|
|
##
|
|
# Convert this Vote to a number.
|
|
#
|
|
def to_i
|
|
self.vote? ? 1 : 0
|
|
end
|
|
|
|
##
|
|
# Is this a 'no' vote.
|
|
#
|
|
def zero?
|
|
self.to_i == 0
|
|
end
|
|
|
|
##
|
|
# Is this a 'yes' vote.
|
|
#
|
|
def one?
|
|
self.to_i == 1
|
|
end
|
|
|
|
##
|
|
# Checks if a user has voted for a Photo. If you pass a User for user it will
|
|
# check for an authenticated user, else it will look for an anonymous vote.
|
|
#
|
|
def self.voted_for?(photo, user)
|
|
c = [ 'photo_id = :pid' ]
|
|
v = { :pid => (photo.respond_to?('id') ? photo.id : photo) }
|
|
if user.respond_to?('id')
|
|
c << 'user_id = :uid'
|
|
v[:uid] = user.id
|
|
else
|
|
c << 'session_id = :uid'
|
|
v[:uid] = user
|
|
end
|
|
self.find :first, :conditions => [ c.join(' AND '), v ]
|
|
end
|
|
|
|
##
|
|
# Does a quick find and collect on the cast votes so you can find all voted
|
|
# photo ids.
|
|
#
|
|
def self.voted_photo_ids(user)
|
|
c = if user.respond_to?('id')
|
|
"votes.user_id = #{user.id}"
|
|
else
|
|
"votes.session_id = '#{user}'"
|
|
end
|
|
self.find(:all, :conditions => c, :select => 'photo_id').collect { |v| v.photo_id }
|
|
end
|
|
|
|
protected
|
|
|
|
##
|
|
# Make sure you can't vote on a photo more than once.
|
|
#
|
|
def unique_for_user
|
|
if self.user.to_s.empty? and self.session_id.empty?
|
|
self.errors.add(:vote, 'must have an owner')
|
|
elsif self.user and Vote.voted_for?(self.photo, self.user)
|
|
self.errors.add(:vote, 'has already been collected for this photo')
|
|
elsif self.session_id and Vote.voted_for?(self.photo, self.session_id)
|
|
self.errors.add(:anonymous, 'vote has already been collected')
|
|
end
|
|
end
|
|
|
|
##
|
|
# Recalc the stats in the Photo for specific stats don't have to query the
|
|
# database.
|
|
#
|
|
def update_photo_stats
|
|
v = if self.frozen?
|
|
-1
|
|
else
|
|
1
|
|
end
|
|
self.photo.votes_count += v
|
|
if self.zero?
|
|
self.photo.zero_votes += v
|
|
else
|
|
self.photo.one_votes += v
|
|
end
|
|
self.photo.save
|
|
end
|
|
end
|