Hi All,
Just wondered how you are meant to get around this little issue:
I have a Company model, which has_many :people and I keep track of the number with a counter cache:
class Company < ActiveRecord::Base has_many :people end
class Person < ActiveRecord::Base belongs_to :company, :counter_cache => true end
Creating new records, deleting them and reassigning people to new companies all works fine.
However, I have a form to edit people which includes a selection list to pick the company: (in /people/edit.html.erb) <%= collection_select(:person, :company_id, @companies, :id, :name, {:prompt => true}) %>
Now here's the killer - Since the controller updates the attributes the company_id is changed but the counter cache is NOT:
if @person.update_attributes(params[:person]) flash[:notice] = 'Person was successfully updated.' format.html { redirect_to(people_path) } format.xml { head :ok } else
Of course, changing the company through the association works perfectly, so the work around is to do something like the following:
@person.company = Company.find params[:person][:company_id] if @person.update_attributes(params[:person]) flash[:notice] = 'Person was successfully updated.'
For extra security and peace of mind, it should also pay to make the company_id field in the People model protected (rather than readonly, which would allow the instance to be out of step with the database):
class Person < ActiveRecord::Base belongs_to :company, :counter_cache => true attr_protected :company_id end
I would submit a patch to do this automatically for all counter caches, but it is beyond my abilities at the moment.