我得到'耙子流产! ... posts_count标记为只读'错误。
我有两个模型:用户和帖子。
users has_many posts.
posts belongs_to :user, :counter_cache => true
我有一个迁移,它将posts_count列添加到users表中,然后计算并记录每个用户的当前帖子数。
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
当我运行迁移时,我收到错误。这当然非常明确,如果我从posts模型中删除:counter_cache声明,例如
belongs_to :user
迁移运行良好。显然,这没有意义,因为你无法以这种方式真正实现它。我错过了什么?
答案 0 :(得分:97)
您应该使用User.reset_counters
来执行此操作。另外,我建议使用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
答案 1 :(得分:3)
好的,文档说明:
计数器缓存列已添加到 包含模型的只读列表 属性通过attr_readonly。
我认为这就是:在模型的定义中声明计数器,从而将“posts_count”属性设置为只读。然后,在迁移过程中,您尝试直接更新它,导致您提到的错误。
快速而肮脏的解决方案是从模型中删除counter_cache声明,运行迁移(为了将所需的列添加到数据库并使用当前的帖子计数填充它),然后重新添加对模型的counter_cache声明。应该工作但是很讨厌并且在迁移期间需要人工干预 - 这不是一个好主意。
我发现this blog post建议在迁移过程中更改模型的只读属性列表,这有点啰嗦,但您可能想尝试一下。