counter_cache实现的问题

我正在耙中止! posts_count被标记为只读错误。

我有两个模型:用户和post。

users has_many posts. posts belongs_to :user, :counter_cache => true 

我有一个迁移,将posts_count列添加到users表,然后计算并logging每个用户的当前post数。

 self.up add_column :users, :posts_count, :integer, :default => 0 User.reset_column_information User.all.each do |u| u.update_attribute( :posts_count, u.posts.count) end end 

当我运行迁移时,我得到了错误。 这当然是非常明确的,如果我从post模型中删除:counter_cache声明,例如

 belongs_to :user 

迁移运行良好。 这显然是没有意义的,因为你不能这样真正实现它。 我错过了什么?

你应该使用User.reset_counters来做到这一点。 此外,我build议使用find_each而不是each因为它会批量迭代集合而不是一次。

 self.up add_column :users, :posts_count, :integer, :default => 0 User.reset_column_information User.find_each do |u| User.reset_counters u.id, :posts end end 

好的,文档说明:

计数器caching列通过attr_readonly被添加到包含模型的只读属性列表中。

我想这是发生了什么事情:你在模型的定义中声明计数器,从而使“posts_count”属性呈现为只读。 然后,在迁移中,您尝试直接更新它,导致您提到的错误。

这个快捷的解决scheme是从模型中删除counter_cache声明,运行迁移(为了将所需的列添加到数据库并用当前的post数填充它),然后重新添加counter_cache声明到该模型。 应该工作,但是很讨厌,在迁移过程中需要人工干预 – 这不是一个好主意。

我发现这个博客文章提出了在迁移过程中改变模型的只读属性列表,但有点让人失望,但您可以试试看。

Interesting Posts