【问题标题】:Problem with counter_cache implementationcounter_cache 实现的问题
【发布时间】:2011-01-21 10:40:17
【问题描述】:

我要'rake 中止了! ...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

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

belongs_to :user

迁移运行良好。这显然是没有意义的,因为您无法以这种方式真正实现它。我错过了什么?

【问题讨论】:

    标签: ruby-on-rails counter-cache


    【解决方案1】:

    您应该使用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
    

    【讨论】:

    • 看来首选方法是:“User.reset_counters u.id, :posts_count”。见api.rubyonrails.org/classes/ActiveRecord/CounterCache.html
    • 对上面的轻微修正(无法再编辑该评论):“User.reset_counters u.id, :posts”
    • @Mike Fischer 不错,看起来 reset_counters 使用的 SQL 调用较少。
    • @gwho 我在4-1-stable 或master 中都没有看到任何一种方法的弃用通知。什么让你有那个想法? github.com/rails/rails/blob/master/activerecord/lib/…
    • 如果代码移动位置,@gwho apidock 会调用任何“已弃用”的内容。我通常会避开那个网站,它经常会让人感到困惑。
    【解决方案2】:

    好的,文档说明:

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

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

    快速而简单的解决方案是从模型中删除 counter_cache 声明,运行迁移(为了将所需的列添加到数据库并使用当前的帖子计数填充它),然后重新添加模型的 counter_cache 声明。应该可以,但是很麻烦,并且在迁移过程中需要人工干预 - 这不是一个好主意。

    我发现this blog post 建议在迁移期间更改模型的只读属性列表,这有点过时,但您可能想尝试一下。

    【讨论】:

    • 感谢您的帮助。我正在使用您建议的解决方法,但正如您所同意的,这不是将产品投入生产的好方法。也感谢您的博客文章,但该 hack 似乎不再起作用(我目前使用的是 rails 3.0.1。)我可能只需要滚动自己的缓存计数器并在应用程序中维护它们。
    • 那篇博文具有误导性或已过时。见this one。
    • 这对我来说是个问题。 counter_cache: true 设置在幕后做一些 attr_readonly 幕后魔术并阻止我的迁移
    • 这种方式在尝试在 Heroku 等远程存储库上执行时会出现问题。上传一个关闭 countercache 的版本,然后迁移,然后上传一个实施 countercache 的版本?嗯。
    猜你喜欢
    • 2021-09-16
    • 2011-04-01
    • 1970-01-01
    • 2011-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多