railsの親モデルから子モデルへのcountをするのは、counter_cacheを使ってみよう
サイトのパフォーマンスをチェックしていたら、おぞましいSQLの発行が行われており、サイトが重くなっていました。
これは気持ち悪いですね。
こんな大量にSQLが発行されていたら、表示速度が無駄に遅くなります。
では、話を今回のモデルの概要です。
Post model(親)に、Cheer model(子)が属しています。
Post model
class Grumble < ActiveRecord::Base has_many :cheers end
Cheer model
class Cheer < ActiveRecord::Base belongs_to :grumble, counter_cache: true end
これに対して、view側での表示の仕方です。
post.cheers.count
発行されていたSQLの中身です。
SELECT COUNT(*) FROM "cheers" WHERE "cheers"."post_id" = ?
SELECT COUNT(*)となっているので、毎回全力でCheerモデルから、post_idを全部のデータから探しています。
これは時間がかかるわけだ。
railsでは、こういう場合の時のために、counter_cacheという機能があります。
counter_cacheを使用すれば、上のSQLの発行がなくなります。
使い方です。
今回の例では、Post model(親)にcheers_countというcolumnを作ります。
rails g migration AddCheersCountToPost cheers_count:integer
migationにdefault: 0を付け加えます。
class AddCheersCountToPost < ActiveRecord::Migration def change add_column :posts, :cheers_count, :integer, default: 0 end end
この後に、Cheer model(子)にcounter_cacheというオプションをつけます。
class Cheer < ActiveRecord::Base belongs_to :grumble, counter_cache: true end
最後にview側の設定です。
post.cheers.size
ここをsizeにしないといけません。
これでSQLの発行がされなくなります。
サイトの表示速度は重要なパフォーマンスなんで、気をつけていきたいですね。