require 'acts_as_votable/helpers/words' module ActsAsVotable module Votable include Helpers::Words def self.included base # allow the user to define these himself aliases = { :vote_up => [ :up_by, :upvote_by, :like_by, :liked_by, :vote_by, :up_from, :upvote_from, :upvote_by, :like_from, :liked_from, :vote_from ], :vote_down => [ :down_by, :downvote_by, :dislike_by, :disliked_by, :down_from, :downvote_from, :downvote_by, :dislike_by, :disliked_by ], :up_votes => [ :true_votes, :ups, :upvotes, :likes, :positives, :for_votes, ], :down_votes => [ :false_votes, :downs, :downvotes, :dislikes, :negatives ], :unvote => [ :unliked_by, :undisliked_by ] } base.class_eval do belongs_to :votable, :polymorphic => true has_many :votes, :class_name => "ActsAsVotable::Vote", :as => :votable do def voters includes(:voter).map(&:voter) end end aliases.each do |method, links| links.each do |new_method| alias_method(new_method, method) end end end end attr_accessor :vote_registered def vote_registered? return self.vote_registered end def default_conditions { :votable_id => self.id, :votable_type => self.class.base_class.name.to_s } end # voting def vote args = {} options = { :vote => true, }.merge(args) self.vote_registered = false if options[:voter].nil? return false end # find the vote _votes_ = find_votes({ :voter_id => options[:voter].id, :voter_type => options[:voter].class.name }) if _votes_.count == 0 # this voter has never voted vote = ActsAsVotable::Vote.new( :votable => self, :voter => options[:voter] ) else # this voter is potentially changing his vote vote = _votes_.first end last_update = vote.updated_at vote.vote_flag = votable_words.meaning_of(options[:vote]) if vote.save self.vote_registered = true if last_update != vote.updated_at update_cached_votes return true else self.vote_registered = false return false end end def unvote args = {} return false if args[:voter].nil? _votes_ = find_votes(:voter_id => args[:voter].id, :voter_type => args[:voter].class.name) return true if _votes_.size == 0 _votes_.each(&:destroy) update_cached_votes self.vote_registered = false if votes.count == 0 return true end def vote_up voter self.vote :voter => voter, :vote => true end def vote_down voter self.vote :voter => voter, :vote => false end # caching def update_cached_votes updates = {} if self.respond_to?(:cached_votes_total=) updates[:cached_votes_total] = count_votes_total(true) end if self.respond_to?(:cached_votes_up=) updates[:cached_votes_up] = count_votes_up(true) end if self.respond_to?(:cached_votes_down=) updates[:cached_votes_down] = count_votes_down(true) end self.update_attributes(updates, :without_protection => true) if updates.size > 0 end # results def find_votes extra_conditions = {} votes.where(extra_conditions) end def up_votes find_votes(:vote_flag => true) end def down_votes find_votes(:vote_flag => false) end # counting def count_votes_total skip_cache = false if !skip_cache && self.respond_to?(:cached_votes_total) return self.send(:cached_votes_total) end find_votes.count end def count_votes_up skip_cache = false if !skip_cache && self.respond_to?(:cached_votes_up) return self.send(:cached_votes_up) end up_votes.count end def count_votes_down skip_cache = false if !skip_cache && self.respond_to?(:cached_votes_down) return self.send(:cached_votes_down) end down_votes.count end # voters def voted_on_by? voter votes = find_votes :voter_id => voter.id, :voter_type => voter.class.name votes.count > 0 end end end