简体   繁体   中英

counter_cache in Rails on a scoped association

I have User model which has_many :notifications . Notification has a boolean column seen and a scope called :unseen which returns all notifications where seen is false .

class User < ApplicationRecord
  has_many :notifications
  has_many :unseen_notifications, -> { unseen }, class_name: "Notification"
end

I know that I can cache the number of notifications if I add a column called notifications_count to users and add counter_cache: true to my belongs_to call in Notification .

But what if I want to cache the number of unseen notifications a user has? Ie cache unseen_notifications.size instead of notifications.size ? Is there a built-in way to do this with counter_cache or do I have to roll my own solution?

According to this blog post , there is no built-in way to use counter caches for scoped associations:

ActiveRecord's counter cache callbacks only fire when creating or destroying records, so adding a counter cache on a scoped association won't work. For advanced cases, like only counting the number of published responses, check out the counter_culture gem.

Other than using an external gem, you could roll your own solution by adding callbacks to your Notification model and adding an integer column (eg, unseen_notifications_count ) to the User model:

# Notification.rb
after_save    :update_counter_cache
after_destroy :update_counter_cache

def update_counter_cache
  self.user.unseen_notifications_count = self.user.unseen_notifications.size
  self.user.save
end

Also see the answers to Counter Cache for a column with conditions? for additional implementation examples of this approach.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM