Edited at

counter_cacheが便利だと思ったはなし


はじめに

railsでcounter_cacheというものがあるのを知った。

今まで例えばいいね機能を付ける場合

rails g model user name:string 

rails g model star user:references

みたいにして

userのstarの数を知りたいときは

stars_count = Star.where(user_id: params[:id]).count

みたいにしていた

だがcounter_cacheを使うとstarが作成されたときに自動的にuserカラムのstars_countにstarの数を入れてくれる


使い方

models/user.rbに


user.rb

class User < ApplicationRecord

has_many :stars
end

models/star.rbに


star.rb

class Star < ApplicationRecord

belongs_to :user, :counter_cache => true
end

とする。

これで終わり。

ちなみにあらかじめuserにstars_countというカラムを作成しておく必要があります。

またstars_countではなくほかのカラム名にしたい場合は

:counter_cache => true

counter_cache: :sample_count

とすればOK


試しに使う

rails g model user name stars_count:integer

rails g model star
rails db:migrate

rails c

user = User.create(name: "counter")
100.times {user.stars.create}

省略

"2019-02-07 12:03:41.796608"], ["updated_at", "2019-02-07 12:03:41.796608"], ["user_id", 2]]
User Update All (0.2ms) UPDATE "users" SET "stars_count" = COALESCE("stars_count", 0) + 1 WHERE "users"."id" = ? [["id", 2]]
(11.3ms) commit transaction
(0.1ms) begin transaction
Star Create (1.2ms) INSERT INTO "stars" ("created_at", "updated_at", "user_id") VALUES (?, ?, ?) [["created_at", "2019-02-07 12:03:41.812850"], ["updated_at", "2019-02-07 12:03:41.812850"], ["user_id", 2]]
User Update All (0.1ms) UPDATE "users" SET "stars_count" = COALESCE("stars_count", 0) + 1 WHERE "users"."id" = ? [["id", 2]]
(12.1ms) commit transaction
(0.1ms) begin transaction
Star Create (1.2ms) INSERT INTO "stars" ("created_at", "updated_at", "user_id") VALUES (?, ?, ?) [["created_at", "2019-02-07 12:03:41.831223"], ["updated_at", "2019-02-07 12:03:41.831223"], ["user_id", 2]]
User Update All (0.1ms) UPDATE "users" SET "stars_count" = COALESCE("stars_count", 0) + 1 WHERE "users"."id" = ? [["id", 2]]
(11.3ms) commit transaction
(0.1ms) begin transaction
Star Create (1.2ms) INSERT INTO "stars" ("created_at", "updated_at", "user_id") VALUES (?, ?, ?) [["created_at", "2019-02-07 12:03:41.847880"], ["updated_at", "2019-02-07 12:03:41.847880"], ["user_id", 2]]
User Update All (0.1ms) UPDATE "users" SET "stars_count" = COALESCE("stars_count", 0) + 1 WHERE "users"."id" = ? [["id", 2]]
(13.2ms) commit transaction
=> 100

user.stars_count
=> 100

みたいにちゃんとできています:sunny: