Polymorphic relationships and counter cache
Asked Answered
D

3

13

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.

Discourtesy answered 21/3, 2012 at 17:11 Comment(0)
H
8

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).

Hanson answered 21/3, 2012 at 18:1 Comment(0)
E
8

you may want to add the counter cache attribute to the attr_readonly list in the associated classes (e.g. class Post; attr_readonly :comments_count; end). http://apidock.com/rails/ActiveRecord/Associations/ClassMethods/belongs_to

:polymorphic

    Specify this association is a polymorphic association by passing true. 
    Note: If you’ve enabled the counter cache, then you may
    want to add the counter cache attribute to the attr_readonly list in
    the associated classes 
    (e.g. class Post; attr_readonly :comments_count; end).
Engagement answered 3/5, 2013 at 15:12 Comment(0)
D
8

It's none business of 'Polymorphic relationships and counter cache', it's about Multiple counter_cache in Rails model

By the way, for 'Polymorphic relationships and counter cache'

class Code < ActiveRecord::Base
  has_many :notes, :as => :noteable
end

class Issue < ActiveRecord::Base
  has_many :notes, :as => :noteable
end

class Note < ActiveRecord::Base
  belongs_to :noteable, polymorphic: true, counter_cache: :noteable_count
end

in your table 'issues', you should have the column 'noteable_count', same as your table 'codes'

Diep answered 27/5, 2017 at 9:51 Comment(3)
This should work in Rails 5, but not versions before thatSwagman
Yes, that's true - it doesn't matter what type of relation do you count, just specify the column with counter and celebrate!Agraphia
you have a type. should be counter_cache: :noteable_countToy

© 2022 - 2024 — McMap. All rights reserved.