기술 글
counter_cache를 사용하여 count 구하기
1:N 모델에서 한 모델에 다른 모델이 몇 개 있는지 확인할 때...
- 표시 날짜
- 읽는 시간
- 1 min read
- Tags
1:N 모델에서 한 모델에 다른 모델이 몇 개 있는지 확인할 때 새로 객체를 생성할 때마다 직접 추가 하거나 count(*) 쿼리를 날려 확인했습니다.
하지만 belongs_to의 counter_cache 옵션을 사용하면 자동으로 카운터를 저장하고 갯수가 업데이트되어 쉽게 파악할 수 있습니다.
## migration 파일
class AddReviewsCountToTables < ActiveRecord::Migration[5.2]
def change
add_column :places, :review_count, :integer, default: 0
end
end
## place.rb
has_many :reviews,
## review.rb
belongs_to :place, counter_cache: :review_count
먼저 필요한 모델에 counter_cache를 저장할 컬럼을 추가하고 review 모델에 카운트가 필요한 belongs_to 관계 뒤에 counter_cache 옵션을 추가하면 끝나게 됩니다.
이제 리뷰가 쓰여질 때마다 해당 Place 모델에 저장된 review_count 칼럼에 1씩 추가되고 place.review_count로 해당 place 객체에 몇개에 리뷰가 작성되었는지 확인 할 수 있습니다.
Place.find_each {|place| Place.reset_counters(place.id, :reviews)}
만약 리뷰 구현이 이미 끝나고 나중에 카운터를 추가하는 상황이고 기존 리뷰들까지 카운트 해야 한다면 위 방법으로 counter_cache를 초기화 할 수 있습니다.
모델이 polymorphic으로 구현되었고 여러개 모델에 연관되어 있는 상황일 때도 동일한 방법으로 구현 가능합니다.
## migration 파일
class AddReviewsCountToTables < ActiveRecord::Migration[5.2]
def change
add_column :users, :reviewable_count, :integer, default: 0
add_column :places, :reviewable_count, :integer, default: 0
end
end
## user.rb, place.rb
has_many :reviews, class_name: 'Review', as: :reviewable
## review.rb
belongs_to :reviewable, polymorphic: true, counter_cache: :reviewable_count
User.find_each {|user| User.reset_counters(user.id, :reviews)}
Place.find_each {|place| Place.reset_counters(place.id, :reviews)}