Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reset counter cache on all data of model

I am looking for a beautiful way to update a counter cache of a given model.

Here are my model:

class GameParticipation < ActiveRecord::Base
  belongs_to :game, counter_cache: true
end

And:

class Game < ActiveRecord::Base
  has_many   :game_participations
end

Isn't it something better than iterating on each element like the following code ?

Game.ids.each {|id| Game.reset_counters(id, :game_participations) }
like image 459
Raphael Pr Avatar asked Sep 11 '14 16:09

Raphael Pr


People also ask

How does a counter cache work?

Instead of counting the number of responses every time the articles are displayed, a counter cache keeps a separate response counter which is stored in each article's database row. The counter updates whenever a response is added or removed.

How do I reset the counter of an object?

For articles that predate the counter cache, the counter will be out of sync, as it's 0 by default. We can “reset” a counter for an object by using the .reset_counters method on it and passing the object's ID and the relation the counter should be updated for.

How to clear the cache for analysis services models?

Clear the Cache for Analysis Services Models 1 Get the object identifierIn Management Studio, right-click an object, select Properties, and copy the value... 2 Run the query See More....

How do I set up the counter_cache for an article?

The counter updates whenever a response is added or removed. This allows the article index to render with one database query, without needing to join the responses in the query. To set it up, flip the switch in the belongs_to relation by setting the counter_cache option. This requires a field to the Article model named responses_count.


1 Answers

To update all the counter cache in one request I found inspiration on http://ryan.mcgeary.org/2016/02/05/proper-counter-cache-migrations-in-rails/

It can be done in one request with SQL :

ActiveRecord::Base.connection.execute <<-SQL.squish
    UPDATE games
    SET game_participations_count = (SELECT count(1)
                               FROM game_participations
                              WHERE game_participations.game_id = games.id)
SQL

It takes much less time to execute since all the updating is done in one request.

like image 187
Raphael Pr Avatar answered Oct 16 '22 06:10

Raphael Pr