Quantcast

Counter caches in RoR eliminate the need to issue an sql query to determine the size of an associated collection. Using counter cache is quite simple. Here’s an example:


class Author < ActiveRecord::Base
  has_many :books
end

class Book < ActiveRecord::Base
  belongs_to :author, :counter_cache => true
end

add_column :authors, :books_count, :integer

Author.first.books.count  # gets the value from the books_count column, 
                              # rather than doing an sql count

There’s a problem if you use this alongside acts_as_paranoid. AAP is a plugin that provides ‘soft delete’ functionality. In order to achieve this, AAP overrides AR finder methods to check the ‘deleted_at’ column to determine if a record has been ‘deleted’. Due to a condition placed on the count (counting only undeleted objects), the counter cache is not used and instead an sql statement is issued.


class Author < ActiveRecord::Base
  has_many :books
end

class Book < ActiveRecord::Base
  acts_as_paranoid
  belongs_to :author, :counter_cache => true
end

Author.first.books.count # SELECT count(*) AS count_all FROM `books` 
                             # WHERE (`books`.author_id = 11524) AND 
                             # (`books`.deleted_at IS NULL OR 
                             # `books`.deleted_at > '2008-07-27 13:27:22') 

Deleting an object from a ‘paranoid’ collection will still do the right thing (decrement the counter cache), making this easy to fix. You just have to add your own count method for the collection.


class Author < ActiveRecord::Base
  has_many :books do
    def count
       books_count
    end
  end
end

Author.first.books.count  # calls the count method, returning
                       # the books counter 

This is also published on Learnhub

Sorry, comments are closed for this article.