2

I am implementing counter_cache concept to my Forums app. It is working fine for one model that has a simple belongs_to association but not working for a polymorphic association.

My app structure is like this. I have 3 models, Forum, Post and Comment.

class Forum < ApplicationRecord
   has_many :posts
end

Post Model:

class Post < ApplicationRecord
  belongs_to :forum, counter_cache: true
  has_many :comments, as: :parent
end

Comment Model:

class Comment < ApplicationRecord
  belongs_to :parent,polymorphic: true, counter_cache: true
  has_many :comments, as: :parent
end

My Comments Model is basically a polymorphic one, so a comment can belong to a post or a comment can belong to another comment (in this way it will be considered a reply of a comment)

I have a posts_count field in Forum model which is working fine and auto-incrementing and decrementing is working.

I also have a comments_count field in Post model. Whenever a new comment is created, the comments_count field is incremented in the associated Post. But when I try to create a comment whose parent (polymorphic association) is another comment (so basically a reply of a comment), I hit an error:

Started POST "/comments" for 103.255.4.86 at 2018-10-18 20:48:39 +0000
Cannot render console from 103.255.4.86! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by CommentsController#create as JS
  Parameters: {"utf8"=>"✓", "comment"=>{"body"=>"testing a reply", "parent_id"=>"812", "parent_type"=>"Comment"}}
  Post Load (0.8ms)  SELECT  "posts".* FROM "posts" WHERE "posts"."id" = $1 LIMIT $2  [["id", 7], ["LIMIT", 1]]
   (0.4ms)  BEGIN
  Comment Load (1.6ms)  SELECT  "comments".* FROM "comments" WHERE "comments"."id" = $1 LIMIT $2  [["id", 812], ["LIMIT", 1]]
  SQL (0.9ms)  INSERT INTO "comments" ("body", "parent_type", "parent_id", "owner_type", "owner_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id"  [["body", "testing a reply"], ["parent_type", "Comment"], ["parent_id", 812], ["owner_type", "User"], ["owner_id", 46], ["created_at", "2018-10-18 20:48:39.141170"], ["updated_at", "2018-10-18 20:48:39.141170"]]
   (0.4ms)  ROLLBACK
Completed 500  in 43ms (ActiveRecord: 7.2ms)



ActiveModel::MissingAttributeError (can't write unknown attribute `comments_count`):

What am I missing here? Any hint would be really appreciated, Thanks!!

Saqib Shahzad
  • 982
  • 12
  • 28

2 Answers2

2

I have got it working by removing counter_cache: true from Comment model and defining my own methods for increment and decrement of the counter in Comment model. So here is my final Comment model:

class Comment < ApplicationRecord
  belongs_to :parent,polymorphic: true,touch: true
  has_many :comments,dependent: :destroy,as: :parent

  after_create_commit { self.parent_post.increment!(:answers_count,1) }
  after_destroy { self.parent_post.decrement!(:answers_count,1) }

  def parent_post
    (self.parent if parent_type == "Post") || self.parent.parent
  end

end

If anyone comes up with another answer please post it here. Thanks.

Saqib Shahzad
  • 982
  • 12
  • 28
0

The counter_culture counter cache gem supports polymorphic associations natively: https://github.com/magnusvk/counter_culture

Dom Eden
  • 111
  • 1
  • 2