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.