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声明到该模型。 应该工作,但是很讨厌,在迁移过程中需要人工干预 – 这不是一个好主意。
我发现这个博客文章提出了在迁移过程中改变模型的只读属性列表,但有点让人失望,但您可以试试看。