about

writing

contact

Adding An Average Column To A Model

By eric

2009-08-14

Using Ruby on Rails is all about what people find to be common uses. These items then become part of the core system. An example of this is counter_cache. For more information on this, I suggest checking out the Railscast on it here.

A little more of an edge case is if you want a column that rather than counting totals, its calculates an average. To me this is just common enough to require a HOWTO and not common enough to be in the core rails system. Hence here is my HOWTO.

Context: Let’s use an example similar to Yelp where there is a business and each business gets reviewed. The review count is handled by the counter_cache so that column already exists in our database.

1

| reviews_count |INT(11)| YES ||0||

The trick here is that every review also has a rating of the business being reviewed. So we are going to use this rating column from the reviews table to calculate the average rating of a business.

Now we are going to use the after_save callback hook. We are using after_save because we want the current change to be entered into the database before we make any calculations. In our reviews model, we are going to the following lines:

Let’s walk through this line by line (Note: The business ID and actual ratings will be different based on your data). First, we grab the average rating from every review of that business. What I would like to note is that by default since it is a callback, the review just added is automagically passed into the method. That is how we are able to access the business_id both to find the average of all the reviews of that business, but to also find the business record to update the average_rating attribute.