Question

I have a Post model which has many ratings and I would like to store the average ratings figure for each post in the post ratings db column. I have a counter cache on the post model which counts the number of ratings.

I have the following code in my post.rb

def update_rating
    if self.ratings_count_changed? 
      self.rating = self.ratings.average(:rating)
    end
  end

I had this as a before_save callback so whenever the post is edited and saved it updates the ratings, not very useful.

Is there a way I can call this method whenever a new rating is created?

Was it helpful?

Solution

One way of getting closer to your goal is to add after_create callback to Rating model:

class Rating < ActiveRecord::Base
  belongs_to :post

  # ...

  after_create :update_post_average_rating
  def update_post_average_rating
    self.post.update_attributes(:rating => self.post.ratings.average(:rating))
  end
end

Or even more OO friendly version:

class Post < ActiveRecord::Base
  has_many :ratings

  # ...

  def update_average_rating
    update_attributes(:rating => self.ratings.average(:rating))
  end
end

class Rating < ActiveRecord::Base
  belongs_to :post

  # ...

  after_create :update_post_average_rating
  def update_post_average_rating
    self.post.update_average_rating
  end
end

OTHER TIPS

Do you think about storing average rating in rating model instead post model? In that case you don't need any callback and you need recalc average by first request after changes.

Instead of before_save on post, do an after_create on the rating because it sounds like you need to update that rating score when a new rating is created, not before the post is saved.

How about putting this into Rating model:

after_create :update_post_average_rating

def update_post_average_rating
  self.post.rating = #....
end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top