Forum: Ruby on Rails Counter Problem

Announcement (2017-05-07): is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see and for other Rails- und Ruby-related community platforms.
556da82f2beca9f655b560fe93a55d1b?d=identicon&s=25 Adam Sosnowski (adams)
on 2007-05-14 18:08
Hi. I have a problem with counters in Rails. The situation looks like
-3 simple models

class Forum < ActiveRecord::Base
  has_many :posts
class Topic < ActiveRecord::Base
  has_many :posts
class Post < ActiveRecord::Base
  belongs_to :topic, :counter_cache => true
  belongs_to :forum, :counter_cache => true

- In migrations i have declared
  t.column :posts_count, :integer, :default => 0
  for Forum and Topic

- Now a simple action

def some_action
  @post =[:id])

  @forum.posts << @post   # The @forums.posts_count is up by 1
  @topic.posts << @post   # The @topic.posts_count is _not_ up by 1

Both, the forum_id and topic_id are set correctly in @post, it saves
into the database and everything else is dandy. But why oh why doesn't
the @topic.posts_count increment ? (oh, obviously if I change the order
of the two crucial lines the effect will be the same - the instance in
the second line won't get the posts_count incremented)

Could anyone come up with a solution ? (apart from making the counters
'by hand')
2da252cc1d2fb3701126171831b50a65?d=identicon&s=25 Dave Coleman (pezdude)
on 2007-05-14 21:06
>   @forum.posts << @post   # The @forums.posts_count is up by 1
>   @topic.posts << @post   # The @topic.posts_count is _not_ up by 1

Just a guess, but I think it only updates on the first attempt because
increment_counter is only called if the it's a new record.

So, for the first one, it's a new record, but for the second it's
existing - so no update.

Do the counters update correctly on save?
6e9db38e16957cc51cf9cee9de399249?d=identicon&s=25 dasil003 (Guest)
on 2007-05-14 21:15
(Received via mailing list)
The fundamental problem is that in order to increment the counter when
an existing record was associated, an extra query would be required to
determine whether that record was already included in the count.  At
that point the performance gain of the counter is lost since you might
as well just query for the COUNT again.  Then there's the whole issue
of deleting posts.  I'm assuming the counter would not decrement
unless you call @forum.posts.delete(id).

In my experience the counter caches are scarily brittle.  If the given
model is ONLY created through the association then they can be
manageable and offer a slight performance benefit, but if you have the
proper index, a COUNT(*) query is extremely fast.

On May 14, 1:06 pm, David Coleman <>
9cace61bc2a5972d44d5e1a1b8c145af?d=identicon&s=25 Bram Whillock (bramski)
on 2007-05-15 00:44
(Received via mailing list)
> > Do the counters update correctly on save?

Very much inline with what dasil said, the rails counters are very
brittle, but they are typically per-object caches, so this should be
alright.  However, to be sure, I recommend in a unit test, trying out.

assert_equal @forum.posts.count, 1
assert_equal @topic.posts.count, 1

Your assertion may very well fail, but you should check log/test.log
and examine what SQL queries Rails dispatched if any.
This topic is locked and can not be replied to.