:counter_cache为总项目

时间:2011-03-16 21:48:40

标签: ruby-on-rails ruby-on-rails-3

我有一套简单的两个相关的“订单”表,它们有很多“line_items”。还有一个与订单项相关联的数量,例如

Order1
line_item a:'为初学者编织篮子',数​​量:3
line_item b:'吸血鬼的假人指南',数量:1

当我建立迁移时,我可以使用以下内容包括数量:

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

它给了我正确数量的项目(4),但我似乎无法在订单模型上执行此操作,因为我无法传递订单项的数量,因此它只是计数订单项数量(2)。

所以在line_item模型中我有:

belongs_to :order, :counter_cache => true

我有什么方法可以指定数量,以便正确地说4而不是2?

2 个答案:

答案 0 :(得分:4)

'counter_cache`功能旨在维护依赖项的计数(而不是总和)。

您可以通过编写几行ruby代码轻松实现此目的。

我们假设您的line_items_sum表中有一个名为orders的列。此列的值应默认为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

现在将回调添加到LineItem类。

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

答案 1 :(得分:1)

我认为最好的办法是编写自己的方法来缓存总量。如果你没有按照“Rails方式”来保留计数器,你最好自己编写。