[Rails] Counter Cache 用法
前言
最近發現常常使用 conuter cache,紀錄一下增加記憶。
使用時機
當有兩個 table 為 1對多關聯,並需要統計關聯 table 的數量時。此時每次存取網頁都需要再統計一次數量,會造成效能低落。 若使用Counter Cache,則可讓每次關聯 table 數量異動時,由程式自動紀錄至主要 table 的 cache 欄位中,之後在網頁存取時就可以直接從 cache 抓取數量,讓使用者感到效能提升。
使用方式
例如: 顯示文章列表(posts)時,也要顯示每篇有多少留言回覆(comments)。
<% @posts.each do |post| %>
主題:<%= post.subject %>
回覆數:<%= post.comments.size %>
<% end %>
此時在取得 post.comments.size
時,實際上存取資料庫(select)的次數會是 comments 的數量
改使用 counter cache,需在 Model 新增一個欄位叫做 comments_count:
rails g migration add_comments_count_to_post comments_count:integer
至 Migration 調整,將 default 設為 0,並把 counter cache 初始化:
class AddPostsCountToTopic < ActiveRecord::Migration
def change
add_column :posts, :comments_count, :integer, :default => 0 #補上 :defalut => 0
Post.pluck(:id).each do |i| ## Post.pluck(:id),表示從Post中取得由id組成的array如[1,2,3,..]
Post.reset_counters(i, :comments) ## 把所有counter cache重算一次
end
end
end
編輯 Models,加入 counter_cache: true
:
class Comment < ActiveRecord::Base
belongs_to :post, counter_cache: true
end
class Post < ActiveRecord::Base
has_many :comments
end
此時再執行
rake db:migrate
這樣同樣的 @post.comments.size
,程式就會自動改抓 cache,就等於自動使用 @post.comments_count
。
備註
- 若不想使用comments_count當欄位名稱,改使用xxx當欄位名稱,可改寫為
counter_cache: :xxx
- pluck用法參考
- reset_counters用法參考
留言