Skip to content

Commit

Permalink
reverted category rating support, plan to implement it differently later
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Reinsch committed Jul 20, 2009
1 parent 7c752bb commit 35f90c3
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 72 deletions.
4 changes: 1 addition & 3 deletions generators/acts_as_rateable_migration/templates/migration.rb
Expand Up @@ -6,15 +6,13 @@ def self.up
t.column :score, :integer
t.column :rateable_id, :integer
t.column :rateable_type, :string, :limit => 32
t.column :category, :string, :null => true, :default => nil
t.timestamps
end

add_index :ratings, [:rateable_id, :rateable_type]
add_index :ratings, :category
end

def self.down
drop_table :ratings
end
end
end
71 changes: 23 additions & 48 deletions lib/acts_as_rateable.rb
Expand Up @@ -6,79 +6,54 @@ def self.included(base)
end

module ClassMethods
# FIXME - rather than the with_scope/opts hacks, do something smarter in the association
def acts_as_rateable(options = {})
options = {:max_rating => 5}.merge(options)
has_many :ratings, :as => :rateable, :dependent => :destroy do
define_method(:options) { options }

def categories
options[:categories]
end

def max_rating
options[:max_rating]
end
has_many :ratings, :as => :rateable, :dependent => :destroy
unless respond_to?(:max_rating)
class_inheritable_accessor :max_rating
attr_protected :max_rating
self.max_rating = options[:max_rating] || 5
end
include ActiveRecord::Acts::Rateable::InstanceMethods
end
end

module InstanceMethods
# Rates the object by a given score. A user id should be passed to the method.
def rate_it(score, user_id, opts = {})
scope_to_category(opts[:category]) do
returning(ratings.find_or_initialize_by_user_id(user_id)) do |rating|
rating.update_attributes!(:score => score, :category => opts[:category])
end
def rate_it(score, user_id)
returning(ratings.find_or_initialize_by_user_id(user_id)) do |rating|
rating.update_attributes!(:score => score)
end
end

# Calculates the average rating. Calculation based on the already given scores.
def average_rating(opts = {})
scope_to_category(opts[:category]) do
avg = ratings.average(:score)
avg || 0.0
end
def average_rating
avg = ratings.average(:score)
avg || 0.0
end

# Rounds the average rating value.
def average_rating_round(opts = {})
average_rating(opts).round
def average_rating_round
average_rating.round
end

# Returns the average rating in percent.
def average_rating_percent(opts = {})
f = 100 / ratings.max_rating.to_f
average_rating(opts) * f
def average_rating_percent
f = 100 / max_rating.to_f
average_rating * f
end

# Checks whether a user rated the object or not.
def rated_by?(user_id, opts = {})
scope_to_category(opts[:category]) do
ratings.exists?(:user_id => user_id)
end
def rated_by?(user_id)
ratings.exists?(:user_id => user_id)
end

# Returns the rating a specific user has given the object.
def rating_by(user_id, opts = {})
scope_to_category(opts[:category]) do
rating = ratings.find_by_user_id(user_id)
rating ? rating.score : nil
end
end

private

# FIXME - this entire category scoping thing could be better
def scope_to_category(category)
yield if category.blank?
Rating.send(:with_scope, :find => {:conditions => {:category => category}}) do
yield
end
def rating_by(user_id)
rating = ratings.find_by_user_id(user_id)
rating ? rating.score : nil
end
end # InstanceMethods

end

end
end
Expand Down
23 changes: 2 additions & 21 deletions lib/rating.rb
@@ -1,9 +1,9 @@
class Rating < ActiveRecord::Base
belongs_to :rateable, :polymorphic => true
validates_presence_of :score
validates_uniqueness_of :user_id, :scope => [:rateable_id, :rateable_type, :category]
validates_uniqueness_of :user_id, :scope => [:rateable_id, :rateable_type]
validate :max_rating_allowed_by_parent
validate :in_category_allowed_by_parent
delegate :max_rating, :to => :rateable

private

Expand All @@ -15,23 +15,4 @@ def max_rating_allowed_by_parent
end
end

def rateable_options
rateable.ratings.options
end

def max_rating
rateable_options[:max_rating]
end

def categories
rateable_options[:categories]
end

def in_category_allowed_by_parent
return if categories.blank?
unless categories.include?(category)
errors.add(:category, "must be one of the following: #{categories.to_sentence(:connector => 'or')}")
end
end

end

0 comments on commit 35f90c3

Please sign in to comment.