使用“counter_cache”时如何调用 after_save 回调?
Posted
技术标签:
【中文标题】使用“counter_cache”时如何调用 after_save 回调?【英文标题】:How can I invoke the after_save callback when using 'counter_cache'? 【发布时间】:2011-05-07 00:46:25 【问题描述】:我有一个为关联启用了 counter_cache 的模型:
class Post
belongs_to :author, :counter_cache => true
end
class Author
has_many :posts
end
我还为每个“作者”使用缓存片段,并且我希望在更新 @author.posts_count
时使该缓存过期,因为该值显示在 UI 中。问题是counter_cache
(increment_counter 和 decrement_counter)的内部似乎没有调用 Author 上的回调,所以除了从 Post 观察者(或缓存)中使缓存过期之外,我无法知道它何时发生扫地机),它看起来并不那么干净。
有什么想法吗?
【问题讨论】:
【参考方案1】:我有类似的要求在计数器更新时做某事,在我的情况下,如果 counter_cache 计数超过某个值,我需要做某事,我的解决方案是重写 update_counters
方法,如下所示:
class Post < ApplicationRecord
belongs_to :author, :counter_cache => true
end
class Author < ApplicationRecord
has_many :posts
def self.update_counters(id, counters)
author = Author.find(id)
author.do_something! if author.posts_count + counters['posts_count'] >= some_value
super(id, counters) # continue on with the normal update_counters flow.
end
end
请参阅update_counters documentation 了解更多信息。
【讨论】:
【参考方案2】:我也无法让它工作。最后我放弃了,写了自己的类似cache_counter的方法,从after_save
回调中调用。
【讨论】:
感谢 Dex,我也会发布我想出的解决方案【参考方案3】:我最终保持 cache_counter 不变,但随后通过 Post 的 after_create 回调强制缓存过期,如下所示:
class Post
belongs_to :author, :counter_cache => true
after_create :force_author_cache_expiry
def force_author_cache_expiry
author.force_cache_expiry!
end
end
class Author
has_many :posts
def force_cache_expiry!
notify :force_expire_cache
end
end
那么 force_expire_cache(author)
是我的 AuthorSweeper 类中的一个方法,它使缓存片段过期。
【讨论】:
【参考方案4】:好吧,我也遇到了同样的问题,最后出现在你的帖子中,但我发现,由于“after_”和“before_”回调是公共方法,你可以执行以下操作:
class Author < ActiveRecord::Base
has_many :posts
Post.after_create do
# Do whatever you want, but...
self.class == Post # Beware of this
end
end
我不知道这样做有多少标准,但是方法是公开的,所以我想是可以的。
如果你想保持缓存和模型分开,你可以使用Sweepers。
【讨论】:
【参考方案5】:我也有观察柜台变化的需求。挖掘 Rails 源代码后,通过直接 SQL 更新更改 counter_column。换句话说,它不会触发任何回调(在您的情况下,它不会在 Post 更新时触发 Author 模型中的任何回调)。
从 rails 源代码,counter_column 也被 after_update 回调改变了。
我的做法是让rails向上,自己更新counter_column:
class Post
belongs_to :author
after_update :update_author_posts_counter
def update_author_posts_counter
# need to update for both previous author and new author
# find_by will not raise exception if there isn't any record
author_was = Author.find_by(id: author_id_was)
if author_was
author_was.update_posts_count!
end
if author
author.update_posts_count!
end
end
end
class Author
has_many :posts
after_update :expires_cache, if: :posts_count_changed?
def expires_cache
# do whatever you want
end
def update_posts_count!
update(posts_count: posts.count)
end
end
【讨论】:
以上是关于使用“counter_cache”时如何调用 after_save 回调?的主要内容,如果未能解决你的问题,请参考以下文章
如何在androidmainfest.xml中调用自动对焦功能
使用ctypes和python并调用libc accept时的EFAULT
如何使用Alamofire Router来组织API调用?(swift Alamofire5)
当我键入 AF.request 时,啥都没有显示,但 Alamofire.request 正在工作,但 .GET 功能仍然没有显示。我如何解码数据