# Correct use of counter caches?

**URL:** <https://www.ruby-forum.com/t/correct-use-of-counter-caches/73550>\
**Category:** Rails\
**Created:** [October 25, 2006, 6:55am UTC](https://www.ruby-forum.com/t/correct-use-of-counter-caches/73550 "2006-10-25T06:55:26Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![sshingler](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/3da27b/32.png) [@sshingler](https://www.ruby-forum.com/u/sshingler)\
**Post date:** [October 25, 2006, 6:55am UTC](https://www.ruby-forum.com/t/correct-use-of-counter-caches/73550/1 "2006-10-25T06:55:26Z")

</div>

I have trouble using :counter\_cache =\> true on some of my belongs\_to  
associations.

When have say, Person which belongs\_to :company, :counter\_cache =\> true  
and I update a Person’s record assigning that person to a different  
company, it appears that the counter is not updated.

Ideally, person.update\_attributes(params[:person]) should handle this  
magically if a new :company\_id is in the params. I have several  
situations where I need to change the belongs\_to association on a model  
instance based on form input. Are counter\_caches useful here? Is there  
a trick to it?

It seems that only company.people \<\< person works.

Am I missing something?

Best,

Steven

---

<div class="post-metadata">

**Author:** ![sshingler](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/3da27b/32.png) [@sshingler](https://www.ruby-forum.com/u/sshingler)\
**Post date:** [October 25, 2006, 7:04am UTC](https://www.ruby-forum.com/t/correct-use-of-counter-caches/73550/2 "2006-10-25T07:04:17Z")

</div>

Counter\_cache is completly broken as of now:

[http://dev.rubyonrails.org/ticket/5050](http://dev.rubyonrails.org/ticket/5050)

You shouldn’t use ANY counters in counters in a class that you use  
AR#save on. The patch at the bottom of the ticker does resolve this,  
but it has to be done directly in the active record code.

---

<div class="post-metadata">

**Author:** ![sshingler](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/3da27b/32.png) [@sshingler](https://www.ruby-forum.com/u/sshingler)\
**Post date:** [October 25, 2006, 7:10am UTC](https://www.ruby-forum.com/t/correct-use-of-counter-caches/73550/3 "2006-10-25T07:10:31Z")

</div>

To clarify what the problem is:  
The counter\_cache isn’t thread safe. You can never use ‘update

  
set my\_count = #’ when dealing with counters, unless you lock the row  
before you do your select, to prevent other updates from being lost.

You should only ever do ‘update table set my\_count = my\_count + #’.  
Unfortunately AR doesn’t handle this currently.

---

<div class="post-metadata">

**Author:** ![sshingler](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/3da27b/32.png) [@sshingler](https://www.ruby-forum.com/u/sshingler)\
**Post date:** [October 25, 2006, 7:32am UTC](https://www.ruby-forum.com/t/correct-use-of-counter-caches/73550/4 "2006-10-25T07:32:18Z")

</div>

Slain W. wrote:

> To clarify what the problem is:  
> The counter\_cache isn’t thread safe. You can never use ‘update
> 
>   
> set my\_count = #’ when dealing with counters, unless you lock the row  
> before you do your select, to prevent other updates from being lost.
> 
> You should only ever do ‘update table set my\_count = my\_count + #’.  
> Unfortunately AR doesn’t handle this currently.
> 
> Okay, I think I understand the severity of this but I am unsure how this  
> relates to my issue.
> 
> Basically, if I am updating a belongs\_to associated object and I am  
> updating the value of the foreign key for the association, no attempt is  
> made by rails to modify the counter\_cache.
> 
> I only use the caches in a non-critical area of the admin section of my  
> site. It is enough to update them periodically. The only thing I have  
> noticed this does affect is pagination.
> 
> If the counter cache is a lower value than the actual number of  
> associated records, pagination will only give me as many pages as the  
> cache value would indicate.
> 
> I will steer clear of dependency on counter caches but they are  
> necessary to cut down queries to the db on result list pages. Perhaps  
> with a little indexing, even that won’t be a problem.
> 
> Steven

---

<div class="post-metadata">

**Author:** ![sshingler](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/3da27b/32.png) [@sshingler](https://www.ruby-forum.com/u/sshingler)\
**Post date:** [October 25, 2006, 8:06am UTC](https://www.ruby-forum.com/t/correct-use-of-counter-caches/73550/5 "2006-10-25T08:06:06Z")

</div>

> Basically, if I am updating a belongs\_to associated object and I am  
> updating the value of the foreign key for the association, no attempt is  
> made by rails to modify the counter\_cache.

AR#save by default saves all fields. I can’t remember exactly what  
happens since I don’t use counter\_cache anymore. Have you checked the  
log to see if it actually is getting updated but that the update is lost  
when you save the save the parent record? This was how I first noticed  
the problem. Also, I’m not sure if the counter\_cache code triggers  
unless you do it thru the parent.

Ie. if you have class Forum which has many Class Article, and you have  
an article\_count in your Forum class, you may need to do  
forum\_instance.articles \<\< Article.new to get that to trigger. Just  
cant remember.

> I only use the caches in a non-critical area of the admin section of my  
> site. It is enough to update them periodically. The only thing I have  
> noticed this does affect is pagination.
> 
> If the counter cache is a lower value than the actual number of  
> associated records, pagination will only give me as many pages as the  
> cache value would indicate.
> 
> I will steer clear of dependency on counter caches but they are  
> necessary to cut down queries to the db on result list pages. Perhaps  
> with a little indexing, even that won’t be a problem.

Or you can patch AR to not include \*\_count fields when doing AR#save,  
and use AR#increment\_counter for the \*\_count fields.
