在模型的所有数据上重置计数器缓存

Rap*_* Pr 6 activerecord ruby-on-rails

我正在寻找一种更新给定模型的计数器缓存的漂亮方法.

这是我的模型:

class GameParticipation < ActiveRecord::Base
  belongs_to :game, counter_cache: true
end
Run Code Online (Sandbox Code Playgroud)

而且:

class Game < ActiveRecord::Base
  has_many   :game_participations
end
Run Code Online (Sandbox Code Playgroud)

这不是比像下面的代码迭代每个元素更好的东西吗?

Game.pluck(:id).map{|g_id| Game.reset_counters(g_id, :game_participations) }
Run Code Online (Sandbox Code Playgroud)

(我正在使用Rails4和activerecord)

Rap*_* Pr 14

要在一个请求中更新所有计数器缓存,我在http://ryan.mcgeary.org/2016/02/05/proper-counter-cache-migrations-in-rails/找到了灵感.

可以使用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
Run Code Online (Sandbox Code Playgroud)

由于所有更新都在一个请求中完成,因此执行所需的时间要少得多.