Selections, updates and counter caches

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.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs