开发者

Atomic arithmetic in Rails

I need to perform some atomic arithmetic in Rails but the only way I've found to do it for single objects is via the crude update_all class method, e.g.:

Account.update_all(["debits = debits + ?", amount], :id => id)

With collection associations, the upda开发者_开发技巧te_all class method should be usable as an association method, since the collection will pass missing method calls on to the class with the relevant scope:

accounts.update_all(["debits = debits + ?", amount])

When dealing with collections, this is much nicer and less repetitive. However this doesn't work for singleton associations, i.e. belongs_to and has_one. The method_missing for AssociationProxy passes through to the target instance, which won't have an update_all instance method (naturally).

Is there a more elegant way to perform this arithmetic? Or is update_all as good as it gets?


I think what you are looking for is the update_counters method. It allows you to specify an arbitrary increment value and still performs an atomic operation:

Account.update_counters id, :debits => amount

It also supports performing the operation on collections of ids without a loop:

Account.update_counters [1, 2, 3, 4, 5], :debits => amount

Check out the most recent Rails 3.0.x documentation:

http://api.rubyonrails.org/classes/ActiveRecord/CounterCache.html#method-i-update_counters


You're not going to beat the performance of update_all on a large number of records by a longshot. Any reason not to use that and wrap it in a transaction?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜