counter_cache 实现的问题
我的耙子要中止了! ... posts_count 被标记为只读错误。
我有两个模型:用户和帖子。
users has_many posts.
posts belongs_to :user, :counter_cache => true
我有一个迁移,它将 posts_count 列添加到用户表中,然后计算并记录每个用户的当前帖子数。
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
当我运行迁移时出现错误。当然,这是非常明确的,如果我从帖子模型中删除 :counter_cache 声明,例如
belongs_to :user
迁移运行正常。显然,这没有意义,因为你无法真正以这种方式实现它。我缺少什么?
I'm getting 'rake aborted! ... posts_count is marked readonly' errors.
I have two models: user and post.
users has_many posts.
posts belongs_to :user, :counter_cache => true
I have a migration which adds the posts_count column to the users table and then calculates and records the current number of posts per user.
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
when I run the migration I get the error. This is pretty clear-cut, of course and if I remove the :counter_cache declaration from the posts model, e.g.
belongs_to :user
the migration runs fine. This obviously, does not make sense because you couldn't really implement it this way. What am I missing?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
![扫码二维码加入Web技术交流群](/public/img/jiaqun_03.jpg)
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您应该使用 User.reset_counters 来执行此操作。此外,我建议使用
find_each
而不是each
,因为它会批量迭代集合,而不是一次迭代全部集合。You should be using
User.reset_counters
to do this. Additionally, I would recommend usingfind_each
instead ofeach
because it will iterate the collection in batches instead of all at once.好的,文档说明:
我认为发生的情况是这样的:您在模型的定义中声明计数器,从而将“posts_count”属性呈现为只读。然后,在迁移中,您尝试直接更新它,导致您提到的错误。
快速而肮脏的解决方案是从模型中删除 counter_cache 声明,运行迁移(以便将所需的列添加到数据库并用当前的帖子计数填充它),然后将 counter_cache 声明重新添加到模型。应该可以工作,但很麻烦,并且在迁移过程中需要手动干预 - 这不是一个好主意。
我发现这篇博文建议更改模型的列表迁移期间的只读属性,它有点过时,但您可能想尝试一下。
OK, the documentation states:
I think this is what happens: you declare the counter in the model's definition, thus rendering the "posts_count" attribute read-only. Then, in the migration, you attempt to update it directly, resulting in the error you mention.
The quick-and-dirty solution is to remove the counter_cache declaration from the model, run the migration (in order to add the required column to the database AND populate it with the current post counts), and then re-add the counter_cache declaration to the model. Should work but is nasty and requires manual intervention during the migration - not a good idea.
I found this blog post which suggests altering the model's list of read-only attributes during the migration, it's a bit oudated but you might want to give it a try.