Os logs do seu servidor Rails estão cheios de linhas como esta:
(0.3ms) SELECT COUNT(*) FROM "comments" WHERE "comments"."post_id" = 1
Ou talvez você apenas queira armazenar o número de filhos que um modelo pai mantém para fazer algumas consultas de cálculo
Configuração
Configurar counter_cache é bastante simples. Consiste apenas em adicionar um novo campo que armazene um valor de contador que será atualizado sempre que um membro for adicionado / removido da coleção através dos callbacks de ActiveRecord .
# app/models/post.rb
class Post < ActiveRecord::Base
has_many :comments
end
# app/models/comment.rb
class Comment < ActiveRecord::Base
belongs_to :post, counter_cache: true
end
Em seguida, criamos a migração:
class AddCommentsCountToPosts < ActiveRecord::Migration
def change
add_column :posts, :comments_count, :integer, default: 0, null: false
# Update the counter for existing records
Post.select(:id) do |result|
Post.reset_counters(result.id, :comments)
end
end
end
E isso é tudo que precisamos fazer! 🙂
Agora podemos facilmente fazer algumas consultas como:
Post.where("created_at > ?", 2.month.ago).average(:comments_count)
Nota 1: Também funciona com associações polimórficas (apesar de parecer precisar de uma configuração adicional
Nota 2: o contador só é atualizado na criação e exclusão do modelo . Se você precisar mudar algo quando for atualizado, você precisará de uma solução alternativa como esta ou você pode usar esta joia
Créditos: ElegantRuby , StackOverflow e guia Rails