Skip to content
This repository
tree: 283d41ed6d
Fetching contributors…

Cannot retrieve contributors at this time

file 102 lines (85 sloc) 3.141 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
require 'active_support/concern'
module Rateit
  extend ActiveSupport::Concern
  

  def rate(stars, user_id, dimension=nil)
    if can_rate? user_id, dimension
      rates(dimension).build do |r|
        r.stars = stars
        r.rater_id = user_id
        r.save!
      end
      update_rate_average(stars, dimension)
    else
      raise "User has already rated."
    end
  end
  
  def update_rate_average(stars, dimension=nil)
    if average(dimension).nil?
      RatingCache.create do |avg|
        avg.cacheable_id = self.id
        avg.cacheable_type = self.class.name
        avg.avg = stars
        avg.qty = 1
        avg.dimension = dimension
        avg.save!
      end
    else
      a = average(dimension)
      a.avg = (a.avg + stars) / (a.qty+1)
      a.qty = a.qty + 1
      a.save!
    end
  end
  
  def average(dimension=nil)
    if dimension.nil?
      self.send "rate_average_without_dimension"
    else
      self.send "#{dimension}_average"
    end
  end
      
  def can_rate?(user_id, dimension=nil)
    val = self.connection.select_value("select count(*) as cnt from rates where rateable_id=#{self.id} and rateable_type='#{self.class.name}' and rater_id=#{user_id} and dimension='#{dimension}'").to_i
    if val == 0
      true
    else
      false
    end
  end
  
  def rates(dimension=nil)
    if dimension.nil?
      self.send "rates_without_dimension"
    else
      self.send "#{dimension}_rates"
    end
  end
  
  def raters(dimension=nil)
    if dimension.nil?
      self.send "raters_without_dimension"
    else
      self.send "#{dimension}_raters"
    end
  end

  module ClassMethods
    
    def rateit_rater
      has_many :ratings_given, :class_name => "Rate", :foreign_key => :rater_id
    end
    
    def rateit_rateable(*dimensions)
      has_many :rates_without_dimension, :as => :rateable, :class_name => "Rate", :dependent => :destroy, :conditions => {:dimension => nil}
      has_many :raters_without_dimension, :through => :rates_without_dimension, :source => :rater
      
      has_one :rate_average_without_dimension, :as => :cacheable, :class_name => "RatingCache",
              :dependent => :destroy, :conditions => {:dimension => nil}
      

      dimensions.each do |dimension|
        has_many "#{dimension}_rates", :dependent => :destroy,
                                       :conditions => {:dimension => dimension.to_s},
                                       :class_name => "Rate",
                                       :as => :rateable
                                       
        has_many "#{dimension}_raters", :through => "#{dimension}_rates", :source => :rater
        
        has_one "#{dimension}_average", :as => :cacheable, :class_name => "RatingCache",
                                        :dependent => :destroy, :conditions => {:dimension => dimension.to_s}
      end
    end
  end
    
end

class ActiveRecord::Base
  include Rateit
end
Something went wrong with that request. Please try again.