I try to add counter_cache to User to count owned Projects.
User has many projects, Project has many Users, but Project belongs to one of them.
So i wrote migration for adding extra count fields for counter_cache.
Comments has no trouble with reset_counter
.
But User.reset_counters user.id, :projects
raise NoMethodError: undefined method `counter_cache_column' for nil:NilClass.
Also counter_cache on projects is working OK. If i add extra project it will increment projects_count field, if i delete one - decrement.
Models
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
Migration
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
i tried to switch from :counter_cache => true
to :counter_cache => :projects_count
.
Same thing.
Should you not tell the models that they have many :team_members
for the :through
calls to work? Try adding:
has_many :team_members
to both the User
and Project
models.
EDIT: Looking at your setup more closely, it seems like the issue is that you're setting the counter cache on the :leader
relation, which has no corresponding inverse on the User
side. I'm not exactly sure which way you want it, but here is how I picture the options:
:lead_projects
associationclass 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
and a migration adding :lead_projects_count
to the :users
table.
:projects_count
counter go through TeamMembers
As per 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
With this option, I think your current migration is sufficient.
Note: I'm just writing code as I go here; please comment if I got the syntax wrong so I can edit my answer for future readers.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With