Usa counter_cache en Rails y mejora el performance

Una característica poco conocida de Rails es el counter_cache el cual permite manejar una columna dentro de tu modelo que lleva el contador de la cantidad de registros de un modelo relacionado, de esta forma podemos ahorrarnos consultas adicionales al modelo relacionado.

Para aclarar, veamos este ejemplo, tenemos el modelo Post

1
2
3
class Post < ActiveRecord::Base
has_many :comments
end

Y el modelo Comment

1
2
3
class Comment < ActiveRecord::Base
belongs_to :post
end

Si queremos mostrar la cantidad de comments que tiene un Post específico, digamos el 1:

1
Post.first.comments.size

En esta forma, activerecord hace un recorrido en el modelo Comment adicional a extraer la información del Post acá podemos usar esta característica de counter_cache para mejorar esto.

Primero creamos una migración para el modelo Post en donde debemos agregar el campo siguiendo la convención del nombre de campo nombremodelorelacionado_count para este caso hacemos:

1
rails g migration AddCommentsCountToPost

Luego en el código de la migración creamos:

1
2
3
4
5
6
7
8
9
10
11
12
class AddCommentsCountToPost < ActiveRecord::Migration
def up
add_column :posts, :comments_count, :integer, default: 0
#Acá actualizamos los contadores en caso que ya tengamos registros en nuestro ambiente
Post.reset_column_information
Post.ids.each { |p| Post.reset_counters p, :comments }
end

def down
remove_column :posts, :comments_count
end
end

Debemos modificar el modelo Comment y agregar counter_cache: true a la asociación:

1
2
3
class Comment < ActiveRecord::Base
belongs_to :post, counter_cache: true
end

Corremos nuestra migración y luego probamos el mismo método:

1
Post.first.comments.size

La consulta generada, sale directamente de la tabla posts y su campo comments_count sin usar comments:

1
SELECT  "posts".* FROM "posts"  ORDER BY "posts"."id" ASC LIMIT 1

Happy coding!

avatar

Blog neyDroid

Desarrollando Vagancias