This project is archived and is in readonly mode.
reset_counter_cache
-
Trevor Turk
I gave this the old college try and wasn't able to figure it out. The problem is getting the table name for the association with the column name for the counter. Good luck to anyone else who'd like to give it a shot - I'd be very interested to see how it's done!
-
Pratik
- Assigned user set to Pratik
-
Mike Breen
- Tag set to active_record, counter_cache, patch
This patch adds Model.reset_counter_cache(:association_name).
-
Pratik
- State changed from incomplete to open
-
Sascha Konietzke
I had some problems with counter cache recently myself.
Mike, your patch doesn't seem to account that update_counters increments or decrements the counters by the given amount and doesn't set them to the new value that you get when counting the associations again.
There might be another method to really set the counters or it is necessary to do something like this before using update_counters:
update_all("#{association_name}_count = 0") -
Mike Breen
Thanks for pointing that out Sascha. I've updated the patch to set the counter to zero first.
-
Max Lapshin
What for to reset counter to 0? Maybe better is real resetting to exact number of records?
-
Mike Breen
@Max
reset_counter_cachedoes reset to the exact number of records, but only after resetting it to zero first.After thinking about this there is really no longer a need to reset the counter_cache to zero initially. It made sense when
reset_counter_cachewas usingupdate_countersbut since that is no longer the case the reset to zero is not necessary.Thanks for taking the time to look at the patch.
-
Mike Breen
After talking with the mysterious "noob" on irc I've updated the patch:
- use #find_each
- use #reflect_on_association to get the counter_cache column name
- use connection.update to issue the update sql statement
-
Mike Breen
- Tag changed from active_record, counter_cache, patch to active_record, bugmash, counter_cache, patch
-
Repository
- State changed from open to committed
(from [1db3a27961a9916d6dff0da056a3595a78e7886c]) Implement ActiveRecord#reset_counter_cache
[#1211 reset_counter_cache state:committed]
Signed-off-by: Jeremy Kemper jeremy@bitsweat.net
http://github.com/rails/rails/commit/1db3a27961a9916d6dff0da056a359... -
Repository
(from [50c28e78c7aa40dc329facbe6131d657d5629bd4]) Implement ActiveRecord#reset_counter_cache
[#1211 reset_counter_cache state:committed]
Signed-off-by: Jeremy Kemper jeremy@bitsweat.net
http://github.com/rails/rails/commit/50c28e78c7aa40dc329facbe6131d6... -
Jeremy Kemper
- Milestone changed from 2.x to 2.3.6
-
Gabe da Silveira
Thanks for the work on this everybody, but I don't agree with the implementation. Resetting all the counter caches like this is not performant. At best you will incur some overhead when all you want is to update a single counter cache, at worst this will be a major ordeal requiring hours or days to run.
It seems to me the API should be inline with update_counters. Attached is a subsequent patch against 2-3-stable to bring the APIs more inline. This lets you run against a single row and update multiple counter caches. The original functionality is then trivial to implement:
find_each { |f| reset_counters(f.id, association) }Now a full-reset that ran by means of a single UPDATE with a GROUPed sub-query to perform the counting — that would be worth pursuing if subselects are included in the minimum requirements for ActiveRecord...
-
Jeremy Kemper
- State changed from committed to open
Nice revisions. Could you forward-port to master too?
-
Gabe da Silveira
Ugh, having all kinds of Ruby and mysql version headaches. I can't get master to run tests right now. But here is the patch applied to master. If you could run the tests that would be awesome.
-
Mike Breen
+1 for the new patch.
Although the original ticket was solving a different use case (something that you would run infrequently, possibly during a migration) this is a workable solution to both use cases.
at worst this will be a major ordeal requiring hours or days to run.
-1 for using FUD to make your case. What is this based on? Running this on Amazon's product table?
-
Gabe da Silveira
What is FUD about the at best / at worst scenario? How would you have me say it?
I don't have time to put together a benchmark, but I've done enough row-wise updates on my app (counts ranging from the thousands to low millions, nothing huge). I don't think it should be controversial to say a very significant percentage of applications are going to have tables with more than a few thousand rows, and that row-wise updates hit scalability issues orders of magnitude before regular selects, updates, joins and other ActiveRecord methods do. And therefore I think the use of find_each should be up to the programmer, which as far as I know is an opinion ActiveRecord respects to-date.
-
Mike Breen
I think how you just put it is perfect :)
Thanks for taking the time to clarify what exactly the worse case scenario is.
-
Repository
- State changed from open to committed
(from [32395899d7c97f69b508b7d7f9b7711f28586679]) Replace reset_counter_cache with reset_counters that has API inline with existing update_counters method
[#1211 reset_counter_cache state:committed]
Signed-off-by: Jeremy Kemper jeremy@bitsweat.net
http://github.com/rails/rails/commit/32395899d7c97f69b508b7d7f9b771... -
Repository
(from [43d2cb8e93e7ff3da4d5b4e3c25272b27812adfc]) Replace reset_counter_cache with reset_counters that has API inline with existing update_counters method
[#1211 reset_counter_cache state:committed]
Signed-off-by: Jeremy Kemper jeremy@bitsweat.net
http://github.com/rails/rails/commit/43d2cb8e93e7ff3da4d5b4e3c25272... -
Mislav
I've cleaned up
update/reset_counterscode (now with more ActiveRecord/Arel) and fixed two bugs with guessing association names. Changes are in my "counter_cache" branch on GitHub. Rails 2.3.x version is also available in "counter_cache_2-3-stable"
