Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails Counter Cache and its implementation

I am trying to get hold of rails counter cache feature but not able to grasp it completely.

Let's say that We have 3 models

A B C

A belongs to B or C depending upon a field key_type and key_id. key_type tells whether A belongs to B or C so if key_type="B" then the record belongs to B otherwise it belongs to C.

In my model a.rb, I have defined following associations:

belongs_to :b, :counter_cache => true, :foreign_key => "key_id"
belongs_to :c, :counter_cache => true, :foreign_key => "key_id"

and

in b and c model files

has_many :as , :conditions => {:key_type => "B"}
has_many :as , :conditions => {:key_type => "C"}

Both B and C Models have a column as as_count

The problem is every time an object of a is created count is increased in the both the models b and c.

Any help is appreciated. Initially i thought that this may work:

belongs_to :b, :counter_cache => true, :foreign_key => "key_id", :conditions => {:key_type => "B"}
belongs_to :c, :counter_cache => true, :foreign_key => "key_id", :conditions => {:key_type => "C"}

But this does not help.

Thanks

like image 531
Ishu Avatar asked Mar 19 '10 09:03

Ishu


People also ask

What is counter cache in Rails?

For any parent model with an associated child model, the counter_cache is an integer database column with the value maintained by the Rails framework. An application should treat it as read-only. The column contains a pre-calculated number of associated children.

What is counter cache?

Counter caches are a built in Rails feature that allows you to track the associated records count by doing almost nothing.

How does Rails query cache work?

Query caching is a Rails feature that caches the result set returned by each query. If Rails encounters the same query again for that request, it will use the cached result set as opposed to running the query against the database again.


2 Answers

It looks like polymorphic associations are the way to go for your issue.

Imagine you have a Comment model and 2 models which can be commented : Post and Profile.

In Post and Profile models :

has_many :comments, :as => :resource

In Comment model :

belongs_to :resource, :polymorphic => true, :counter_cache => true

Don't forget to add the "comments_count" column in both Profile and Post models and voilà !

like image 142
kouak Avatar answered Sep 26 '22 06:09

kouak


See http://blog.locomotivellc.com/post/4120559953/counter-cache-polymorphism for a demo.

like image 38
Martin Streicher Avatar answered Sep 23 '22 06:09

Martin Streicher