见代码说话
[1] pry(main)> Node.last.posts
Node Load (0.2ms) SELECT `nodes`.* FROM `nodes` ORDER BY `nodes`.`id` DESC LIMIT 1
Post Load (0.4ms) SELECT `posts`.* FROM `posts` WHERE `posts`.`node_id` = 5
=> []
[2] pry(main)> Post.first.node = Node.last
Node Load (0.1ms) SELECT `nodes`.* FROM `nodes` ORDER BY `nodes`.`id` DESC LIMIT 1
SQL (0.3ms) UPDATE `nodes` SET `posts_count` = COALESCE(`posts_count`, 0) + 1 WHERE `nodes`.`id` = 5
SQL (0.3ms) UPDATE `nodes` SET `posts_count` = COALESCE(`posts_count`, 0) - 1 WHERE `nodes`.`id` = 1
=> #<Node id: 5, name: "ttt", cover: nil, description: nil, created_at: "2013-01-18 21:34:14", updated_at: "2013-01-18 22:15:41", posts_count: 0, state: "publish">
[3] pry(main)> Post.first.node
=> #<Node id: 1, name: "System", cover: nil, description: "", created_at: "2012-12-07 18:29:00", updated_at: "2012-12-07 18:40:03", posts_count: 4, state: "system">
[4] pry(main)> Node.last.posts_count
Node Load (0.4ms) SELECT `nodes`.* FROM `nodes` ORDER BY `nodes`.`id` DESC LIMIT 1
=> 1
[5] pry(main)> Node.last.posts
Node Load (0.4ms) SELECT `nodes`.* FROM `nodes` ORDER BY `nodes`.`id` DESC LIMIT 1
Post Load (0.3ms) SELECT `posts`.* FROM `posts` WHERE `posts`.`node_id` = 5
=> []
[6] pry(main)> Node.last.posts_count
Node Load (0.4ms) SELECT `nodes`.* FROM `nodes` ORDER BY `nodes`.`id` DESC LIMIT 1
=> 1
在给 post 的 node 赋值时 counter 便发生 update,但此时 post 不一定会被 save,这样就造成了不一致性,此外,更新 node_id 时不会更新 counter 阅读了源码,发现似乎就是这么设计的,并且在单元测试中也是按照这个逻辑去做的。
十分不解这样设计的目的,为什么不在更新之后更新 counter?我写了一个 patch,正在犹豫要不要 pr