【问题标题】:reset_counters raise undefined method error, but works fine on similiar relationreset_counters 引发未定义的方法错误,但在类似的关系上工作正常
【发布时间】:2014-05-11 19:34:19
【问题描述】:

我尝试将 counter_cache 添加到 User 以计算拥有的 Projects

用户有很多项目,项目有很多用户,但项目属于其中之一。

所以我写了迁移来为 counter_cache 添加额外的计数字段。

评论reset_counter没有问题。

但是User.reset_counters user.id, :projects 引发 NoMethodError: undefined method `counter_cache_column' for nil:NilClass

项目上的 counter_cache 也工作正常。如果我添加额外的项目,它将增加 projects_count 字段,如果我删除一个 - 减量。

模型

class User < ActiveRecord::Base
  has_many :projects, :through => :team_members
  has_many :team_members

class TeamMember < ActiveRecord::Base
  belongs_to :user
  belongs_to :project

class Project < ActiveRecord::Base
  has_many :users, :through => :team_members
  has_many :team_members
  belongs_to :leader, :class_name => :User, :counter_cache => true

class Comment < ActiveRecord::Base
  belongs_to :user, :counter_cache => true

迁移

class AddCounters < ActiveRecord::Migration
  def up
    add_column :users, :comments_count, :integer, :default => 0
    add_column :users, :projects_count, :integer, :default => 0 

    User.reset_column_information

    User.find_each do |user| 
      User.reset_counters user.id, :comments #all fine

      User.reset_counters user.id, :projects #raise NoMethodError
                                             #undefined method `counter_cache_column'
                                             #for nil:NilClass
    end
  end

  def down
    remove_column :users, :projects_count
    remove_column :users, :comments_count
  end
end

我尝试从:counter_cache =&gt; true 切换到:counter_cache =&gt; :projects_count

同样的事情。

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3


    【解决方案1】:

    难道你不应该告诉模型他们有很多:team_members 来调用:through 吗?尝试添加:

    has_many :team_members
    

    适用于UserProject 型号。


    编辑:更仔细地查看您的设置,似乎问题在于您在 :leader 关系上设置了计数器缓存,而在 User 上没有相应的逆边。我不确定你想要哪种方式,但这是我对选项的描述:

    选项 1:给用户一个单独的:lead_projects 关联

    class User < ActiveRecord::Base
      has_many :lead_projects, :class_name => :Project, :inverse_of => :leader
    
    class Project < ActiveRecord::Base
      belongs_to :leader, :class_name => :User, :counter_cache => :lead_projects_count, :inverse_of => :lead_projects
    

    以及将:lead_projects_count 添加到:users 表的迁移。

    选项 2:使 :projects_count 计数器通过 TeamMembers

    根据this similar answer

    class User < ActiveRecord::Base
      has_many :team_members
      has_many :projects, :through => :team_members
    
    class TeamMember < ActiveRecord::Base
      belongs_to :user, :counter_cache => :projects_count
      belongs_to :project
    
    class Project < ActiveRecord::Base
      has_many :team_members
      has_many :users, :through => :team_members
    

    有了这个选项,我认为你当前的迁移就足够了。


    注意:我只是在这里写代码;如果我的语法错误,请发表评论,以便我可以为未来的读者编辑我的答案。

    【讨论】:

    • 看起来是一个公认的答案,今天试一试,是的,在 Project 和 User 模型中都有 has_many :team_members 我只是忘了添加这些行
    猜你喜欢
    • 1970-01-01
    • 2014-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-07
    • 2019-10-21
    • 2018-10-28
    • 1970-01-01
    相关资源
    最近更新 更多