Track sum of some fields in the association - "sum_cache"
Asked Answered
S

2

9

I have tables 'orders' and 'items' with has_many association in the model.

class Order < ActiveRecord::Base
has_many :items

class Item < ActiveRecord::Base
belongs_to :order

Item consists of 'quantity' field, and Order consists of 'quantity_sum' field to track sum of associated items quantity.

For eg:

Order 1 : name='Toms shopping cart', quantity_sum=12
Item 1 : name='T-shirt', quantity=10
Itme 2 : name='Shoes',   quantity=2

I have been looking for a way so that whenever new item is added/edited/deleted, the field 'quantity_sum' of Order gets updated automatically. Presently I have been using after_save method in Item, to update 'quantity_sum' field of Order.

Is there any other neat way of doing this besides 'after_save' ???

Similar to "counter_cache" for tracking count of associations, does rails have support for automatically keeping track of sum of some fields in the association?

Thanks

Shamrao answered 8/8, 2011 at 8:49 Comment(1)
the callback method is correct : https://mcmap.net/q/1319940/-counter_cache-for-total-itemsAnnorah
G
3

Remove the quantity_sum field from your table and add a quantity_sum method to the order class that sums up the quantity_values

class Order < ActiveRecord::Base
  has_many :items

  def quantity_sum
    self.items.sum(:quantity)
  end
end

Should do the trick. All you then need to do is remove any code you may have that updates the quantity_sum field. You will find that because the name of the method is the same as the field name (That you must not forget to delete) you won't have to refactor any of your code that makes use of it.

Obviously you need to be careful not to use this field unneccesarily like in a list of all orders in the system as this will be quite heavy on the database. O.K for a few hundred records but you'll notice a performance issue over thousands of orders.

Don't forget to remove that quantity_sum field from the order table

Gerard answered 8/8, 2011 at 12:40 Comment(1)
Its true, but the method quantity_sum fires up new queries whenever it gets called. If there are large numbers of items under a same order, huge number of queries get fired, resulting in increased server response-time. It is to avoid this, I had considered storing the sum in the database itself.Shamrao
P
0

I think that this gem is what your'e looking for.
Look under "Totaling instead of counting" in the docs.
It should allow you to to something like this:

class Item < ActiveRecord::Base
  belongs_to :order
  counter_culture :order, :column_name => 'quantity_sum', :delta_column => 'quantity'
end

class Order < ActiveRecord::Base
  has_many :items
end
Pollinosis answered 9/2, 2016 at 7:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.