« Deep Integration of Ruby with Semantic Web Ontologies | Main | Hiring Me As a Consultant / Part-time CTO »

August 22, 2011

Adding a Counter Cache to Existing Records

Adding a counter cache to a has_many/belongs_to ActiveRecord relationship after the underlying records have been around awhile is one of those tasks that tends to trip up Rails newbies.

Here's an example migration showing the necessary steps.

  1. Add the counter_cache column as an integer. (If following normal rails convention, name the column with the plural name of the has_many association followed by _count)
  2. Make sure that the column is set to disallow null values and defaults to 0.
  3. Reset the counters for existing records. The reset_counters method is not smart enough to take an array of ids, so you have to call it for each record you want updated.
class AddCommentsCountToNominations < ActiveRecord::Migration
  def self.up
    add_column :nominations, :comments_count, :integer, null:false, default: 0
# reset cached counts for nominations with comments only
    ids = Set.new
    Comment.all.each {|c| ids << c.nomination_id}
    ids.each do |nomination_id|
      Nomination.reset_counters(nomination_id, :comments)
    end
  end
  def self.down
    remove_column :nominations, :comments_count
  end
end

The :counter_cache option is covered in detail on pages 195-196 of my book The Rails 3 Way, including some interesting gotchas.


If you read this far you should probably follow me on twitter:

TrackBack

TrackBack URL for this entry:
http://www.typepad.com/services/trackback/6a00e54fdca9118833015434baeded970c

Listed below are links to weblogs that reference Adding a Counter Cache to Existing Records:

Sponsored By

Flattr

or visit my my homepage

My Companies

My Latest Books

My Book Series