views:

740

answers:

1

How can I roll my own counter cache for a self-referential many-to-many relationship that uses has_many :through?

I need to track the number of citations and references for each article

I'm using roughly the code from the answer to this question:

class Publication < ActiveRecord::Base
  has_many :citations
  has_many :cited_publications, :through => :citations, :source => :reference
  has_many :references, :foreign_key => "reference_id", :class_name => "Citation"
  has_many :refered_publications, :through => :references, :source => :publication
end

class Citation < ActiveRecord::Base
  belongs_to :publication
  belongs_to :reference, :class_name => "Publication"
end
+1  A: 

The Rails counter cache mechanism uses the increment_counter and decrement_counter methods internally. You should just be able to invoke those methods from the standard ActiveRecord callbacks.

Something like this should give you the idea:

class Citation < ActiveRecord::Base
  belongs_to :publication
  belongs_to :reference, :class_name => "Publication"

  after_create  :increment_counter_cache
  after_destroy :decrement_counter_cache

  private
  def decrement_counter_cache
    Publication.decrement_counter("citations_counter", publication_id)
  end

  def increment_counter_cache
    Publication.increment_counter("citations_counter", publication_id)
  end

end

John Topley
Thanks John. That was about 1/2 of what I needed to know but it got me going. I actually had to increment and decrement both the publication_id article's count and the reference_id article's count.
srboisvert
Good, I'm glad it helped. I thought that you'd have to increment both.
John Topley