2

我有一个模型:

class Account < ActiveRecord::Base

  has_many :payments
  has_many :purchases

  def balance
    payments.sum(:dollar_amount) - purchases.map{|p| p.dollar_amount}.sum
  end

end

我想记住 balance 方法并将其存储在 memcached 中。当然,问题是缓存值需要在任何时候创建付款或购买时过期。我可以在付款和购买的 after_save 回调中插入代码,以使他们帐户的缓存余额过期,但在我看来,如果我可以这样说的话,会更容易理解/维护:

cached_memoize :balance, :depends_on => [:payments, :purchases]

是否有现有的 gem/插件可以做到这一点?在我开始自己写之前,这是个好主意吗?我看到的缺点是,对于正在修改 Purchase 的 Dollar_amount 方法的人来说,他们需要考虑缓存问题可能不太明显(如果他们无意中引入了对另一个模型的依赖,比如 SubPurchase 或其他东西,它会搞砸的。)但是由于这无论如何都不是很明显,我认为拥有一个简洁的声明性语法是值得的 - 至少在它中断时,很清楚如何修复它。

想法?

编辑:为了响应语义艺术的回答,我将更明确地说明“只需将过期时间放在相关回调中”方法的问题 - 问题是你最终会在整个代码库中过期 - 它从 after_save 回调开始付款,但也许它在购买的单独观察者中,然后你有多态关联、继承树等。我提出的语法迫使开发人员将所有这些案例放在一个整齐的列表中。这样,当您收到诸如“用户余额有时不同步并且他们不太确定如何复制问题”之类的错误报告时,更容易弄清楚发生了什么。

4

3 回答 3

1

I'd consider another approach: have a balance field on the account. Use callbacks (after_save, etc.) on the Purchase and SubPurchase models to update the balance field on the parent Account. Your balance only changes when the other models are modified and you never have to worry about it being stale.

于 2009-05-08T19:58:49.947 回答
0

不确定这是您正在寻找的,但它可能会有所帮助。

http://railscasts.com/episodes/137-memoization

于 2009-05-09T19:23:03.203 回答
0

sounds to me like you want to fork cache_fu, and add an option that magically sprinkles the after_saves across the dependent records. I dig having your dependencies in 1 place.

于 2009-05-08T20:30:24.033 回答