magnusvk/counter_culture

Request: Callback support on parent models

Closed this issue · 1 comments

We have this denormalized data model:

books -< comments -< replies
class Book < ActiveRecord::Base
  has_many :comments

  after_save :persist_calculated_comments_and_replies_count

  def persist_calculated_comments_and_replies_count
    return unless saved_changes['comments_count'] || saved_changes['replies_count']
    self.update(comments_and_replies_count: (self.comments_count + self.replies_count))
  end
end

class Comment < ActiveRecord::Base
  has_many :replies
  belongs_to :book
  counter_culture :book, column_name: 'comments_count'
end

class Reply < ActiveRecord::Base
  belongs_to :comment
  counter_culture [:comment, :book], column_name: 'replies_count'
end

Books should have a combined comments and replies count. But, combining comments and replies into a single self-referential table is not an option.

The Rails way is to use a callback to recalculate the aggregate count whenever one of these two changes, however, the implementation uses update_all internally, which does not trigger AR callbacks in here:

klass.where(primary_key => id_to_change).update_all updates.join(', ')

I am well aware this is for performance reasons, but I don't see an option to run callbacks on each counter cache update, would be nice to have an additional option to run callbacks explicitly, e.g.

  counter_culture :book, column_name: 'comments_count', callback: :persist_calculated_comments_and_replies_count

Thoughts?

Yeah this isn't possible with callbacks here. I think what might work is setting the column_name in both Comment and Book to the same column name. That way they'd both increment and decrement the same column and that column should have the sum.