按要求加减指定计数器的值、统计数目的加一、统计数目的减一、重置计数器的值。
# 更新计数器的值
update_counters(id, counters)
# 下面这两个方法基于 update_counters
increment_counter(counter_name, id)
decrement_counter(counter_name, id)
# 当计数出错时,可用它来校正
reset_counters(id, *counters)
这几条命令直接转化成 sql 语句,所以性能上要比普通的"给对象的计数器赋值,然后保存对象"要快,并且准确性得到了更高的保证。
之前没有统计数目,新增统计数目,或之前的统计数目存在错误,使用 reset_counters 你可以又快、又准确的得到统计数目。
update_counters(id, counters)
计数器实现。在它基础上通常有加一、减一操作,但也可以单独使用。
考虑到并发,这里并不只是Rails层面的get,然后set。而是在SQL层面"真正执行时"才增量加减(但没有用锁机制)。下面的加一、减一方法都是这样。
# 注意:参数是字段名
Post.update_counters 3, comments_count: +1
UPDATE "posts" SET "comments_count" = COALESCE("comments_count", 0) + 1 \n
WHERE "posts"."id" = 3
# 原来没有使用计数器,或因为某种原因计数错误。现在我们要使用或修正计数器。
Post.update_counters 3, comments_count: post.comments.count
increment_counter(counter_name, id)
给 counter_name 字段进行加一。
decrement_counter(counter_name, id)
给 counter_name 字段进行减一。
reset_counters(id, *counters)
上文提到的"新增计数器",也可用此方法实现。
# 注意:参数是关系表名(可以是多个),而不是字段名
Post.reset_counters(3, :comments)
SELECT "posts".* FROM "posts" WHERE "posts"."id" = ? LIMIT 1 [["id", 3]]
SELECT COUNT(*) FROM "comments" WHERE "comments"."post_id" = ? [["post_id", 3]]
UPDATE "posts" SET "comments_count" = 2 WHERE "posts"."id" = 3
基于SQL层面,重置(理解为校正,而不是归零)一个或多个计数器的值。计数器有时候会不准,特别是我们用来计数关联对象的个数,而自己又手动删除它们。
Note: counter_cache 的 attribute 默认是 read_only