views:

57

answers:

3

I am trying to calculate the average (mean) rating for all entries within a category based on the following model associations ...

class Entry < ActiveRecord::Base      
  acts_as_rateable
  belongs_to :category
  ...
end


class Category < ActiveRecord::Base
  has_many :entry
  ...
end


class Rating < ActiveRecord::Base
  belongs_to :rateable, :polymorphic => true
  ...
end

The rating model is handled by the acts as rateable plugin, so the rateable model looks like this ...

  module Rateable #:nodoc:
  ...

    module ClassMethods
      def acts_as_rateable
        has_many :ratings, :as => :rateable, :dependent => :destroy
        ...
      end
    end
    ...
  end

How can I perform the average calculation? Can this be accomplished through the rails model associations or do I have to resort to a SQL query?

A: 

Could you use a named_scope or custom method on the model. Either way it would still require some SQL since, if I understand the question, your are calculating a value.

In a traditional database application this would be a view on the data tables.

So in this context you might do something like... (note not tested or sure it is 100% complete)

class Category  
  has_many :entry do  
    def avg_rating()  
       @entries = find :all
       @entres.each do |en|
          @value += en.rating
    end  
    return @value / entries.count
  end


 end
Grant Sayer
though if you get a AVG group function in SQL it sure will be faster
Don
+1  A: 

The average method is probably what you're looking for. Here's how to use it in your situation:

@category.entries.average('ratings.rating', :joins => :ratings)
Andy Gaskell
I am keenly aware of the average method, but I'm not sure how to apply it to this situation. I am interested in finding the average (mean) for all entries within a specific category.
crh
Of course! Perfect! Thanks. I was beginning to think I was going crazy.
crh
A: 

Edit - Check out EmFi's revised answer.

I make no promises but try this

class Category
  def average_rating    
    Rating.average :rating, 
      :conditions => [ "type = ? AND entries.category_id = ?", "Entry", id ],
      :join => "JOIN entries ON rateable_id = entries.id"
  end
end
Mike