# Selections, updates and counter caches

**URL:** <https://www.ruby-forum.com/t/selections-updates-and-counter-caches/133126>\
**Category:** Rails\
**Created:** [March 28, 2008, 4:00am UTC](https://www.ruby-forum.com/t/selections-updates-and-counter-caches/133126 "2008-03-28T04:00:35Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![starmaerker](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/e9bcb4/32.png) [@starmaerker](https://www.ruby-forum.com/u/starmaerker)\
**Post date:** [March 28, 2008, 4:00am UTC](https://www.ruby-forum.com/t/selections-updates-and-counter-caches/133126/1 "2008-03-28T04:00:35Z")

</div>

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.
