Search code examples
ruby-on-railsruby-on-rails-3polymorphic-associations

Polymorphic relationships and counter cache


So I have an app with a 2 different models, Comments and Replies, each of which you can either Agree or Disagree, so I have a polymorphic model called Emotion. Here is my code for these:

class Comment < ActiveRecord::Base
  belongs_to :user
  has_many :replies
  has_many :emotions, :as => :emotionable
end



class Reply < ActiveRecord::Base
  belongs_to :user
  belongs_to :comment
  has_many :emotions, :as => :emotionable
end

class Emotion < ActiveRecord::Base
  belongs_to :emotionable, :polymorphic => :true  
end

So this all works fine, but I'm going to need to add a counter cache for both Comment and Reply in order to get the size of the Agrees and Disagree for each Object. In all of the docs, it has examples for doing counter cache with normal polymorphic associations, not one with an extra condition in it. For reference, by schema for Emotion looks like this:

create_table "emotions", :force => true do |t|
  t.integer  "user_id"
  t.string   "emotion"
  t.integer  "emotionable_id"
  t.string   "emotionable_type"
  t.datetime "created_at",       :null => false
  t.datetime "updated_at",       :null => false
end

TL:DR - I need to be able to call @commet.agrees_count, @comment.disagrees_count, @reply.agrees_count and @reply.disagrees_count on a polymorphic association through a counter cache. So Comment and Reply will need 2 counter caches.


Solution

  • My suggestion would be to manually increment or decrement your counter cache in an after_commit callback so that you can test if the record was persisted and it updates outside of the transaction. This is because it will make your code more explicit, and less mysterious on how and when the cache is updated or invalidated.

    Also manually updating the cache gives you extra flexibility if for example you wanted to give some users more authority when they agree or disagree with a comment (e.g. karma systems).