Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

:counter_cache for total items

I hava a simple set of two related tables of an 'order' that has many 'line_items'. There is also a quantity associated to a line item, e.g.

Order1
line_item a: 'basket weaving for beginners', quantity: 3
line_item b: 'a dummies guide to vampirism', quantity: 1

When I establish the migration I can include the quantity using:

Order.find(:all).each do |o|
  o.update_attribute :line_items_count, o.line_items.map(&:quantity).sum
end

which gives me the correct number of items (4), but I don't appear to be able to do it on the Order model because I'm unable to pass in the quantity of line items, and so it just counts the number of line items (2).

So in the line_item model I have:

belongs_to :order, :counter_cache => true

Is there any way I can specify the quantity so that it correctly says 4 instead of 2?

like image 972
GrahamJRoy Avatar asked May 08 '26 22:05

GrahamJRoy


1 Answers

The 'counter_cache` feature to meant to maintain the count(not the sum) of dependent items.

You can easily achieve this by writing few lines of ruby code.

Let us assume that you have a column called line_items_sum in your orders table. The value of this column should default to 0.

class AddLineItemsSumToOrder < ActiveRecord::Migration
  def self.up
    add_column :orders, :line_items_sum, :integer, :default => 0
  end

  def self.down
    remove_column :orders, :line_items_sum
  end
end


class Order < ActiveRecord::Base
  has_many :line_items
end

Now add the callback to the LineItem class.

class LineItem < ActiveRecord::Base
  validates_numericality_of :quantity
  belongs_to :order
  after_save :update_line_items_sum

private
  def update_line_items_sum
    return true unless quantity_changed?
    Order.update_counters order.id, 
      :line_items_sum => (quantity - (quantity_was || 0))
    return true
  end
end
like image 127
Harish Shetty Avatar answered May 10 '26 12:05

Harish Shetty