Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
181 lines (151 sloc) 4.64 KB
module MakeVoteable
module Voter
extend ActiveSupport::Concern
included do
has_many :votings, :class_name => "MakeVoteable::Voting", :as => :voter
end
module ClassMethods
def voter?
true
end
end
# Up vote a +voteable+.
# Raises an AlreadyVotedError if the voter already up voted the voteable.
# Changes a down vote to an up vote if the the voter already down voted the voteable.
def up_vote(voteable)
check_voteable(voteable)
voting = fetch_voting(voteable)
if voting
if voting.up_vote
raise Exceptions::AlreadyVotedError.new(true)
else
voting.up_vote = true
voteable.down_votes -= 1
self.down_votes -= 1 if has_attribute?(:down_votes)
end
else
voting = Voting.create(:voteable => voteable, :voter_id => self.id, :voter_type => self.class.to_s, :up_vote => true)
end
voteable.up_votes += 1
self.up_votes += 1 if has_attribute?(:up_votes)
Voting.transaction do
save
voteable.save
voting.save
end
true
end
# Up votes the +voteable+, but doesn't raise an error if the votelable was already up voted.
# The vote is simply ignored then.
def up_vote!(voteable)
begin
up_vote(voteable)
success = true
rescue Exceptions::AlreadyVotedError
success = false
end
success
end
# Down vote a +voteable+.
# Raises an AlreadyVotedError if the voter already down voted the voteable.
# Changes an up vote to a down vote if the the voter already up voted the voteable.
def down_vote(voteable)
check_voteable(voteable)
voting = fetch_voting(voteable)
if voting
unless voting.up_vote
raise Exceptions::AlreadyVotedError.new(false)
else
voting.up_vote = false
voteable.up_votes -= 1
self.up_votes -= 1 if has_attribute?(:up_votes)
end
else
voting = Voting.create(:voteable => voteable, :voter_id => self.id, :voter_type => self.class.to_s, :up_vote => false)
end
voteable.down_votes += 1
self.down_votes += 1 if has_attribute?(:down_votes)
Voting.transaction do
save
voteable.save
voting.save
end
true
end
# Down votes the +voteable+, but doesn't raise an error if the votelable was already down voted.
# The vote is simply ignored then.
def down_vote!(voteable)
begin
down_vote(voteable)
success = true
rescue Exceptions::AlreadyVotedError
success = false
end
success
end
# Clears an already done vote on a +voteable+.
# Raises a NotVotedError if the voter didn't voted for the voteable.
def unvote(voteable)
check_voteable(voteable)
voting = fetch_voting(voteable)
raise Exceptions::NotVotedError unless voting
if voting.up_vote
voteable.up_votes -= 1
self.up_votes -= 1 if has_attribute?(:up_votes)
else
voteable.down_votes -= 1
self.down_votes -= 1 if has_attribute?(:down_votes)
end
Voting.transaction do
save
voteable.save
voting.destroy
end
true
end
# Clears an already done vote on a +voteable+, but doesn't raise an error if
# the voteable was not voted. It ignores the unvote then.
def unvote!(voteable)
begin
unvote(voteable)
success = true
rescue Exceptions::NotVotedError
success = false
end
success
end
# Returns true if the voter voted for the +voteable+.
def voted?(voteable)
check_voteable(voteable)
voting = fetch_voting(voteable)
!voting.nil?
end
# Returns true if the voter up voted the +voteable+.
def up_voted?(voteable)
check_voteable(voteable)
voting = fetch_voting(voteable)
return false if voting.nil?
return true if voting.has_attribute?(:up_vote) && voting.up_vote
false
end
# Returns true if the voter down voted the +voteable+.
def down_voted?(voteable)
check_voteable(voteable)
voting = fetch_voting(voteable)
return false if voting.nil?
return true if voting.has_attribute?(:up_vote) && !voting.up_vote
false
end
private
def fetch_voting(voteable)
Voting.where(
:voteable_type => voteable.class.to_s,
:voteable_id => voteable.id,
:voter_type => self.class.to_s,
:voter_id => self.id).try(:first)
end
def check_voteable(voteable)
raise Exceptions::InvalidVoteableError unless voteable.class.voteable?
end
end
end