Search code examples
ruby-on-railsruby-on-rails-3has-manysingle-table-inheritancecounter-cache

counter_cache in single table inheritance


I am wondering if the counter_cache would work in single table inheritance.

For these models:

class User
  has_many :questions
end

class Question
  belongs_to :user, :counter_cache => true
end

class SimpleQuestion < Question
end
class ComplexQuestion < Question
end

So will the following counters work?

create_table(:users) do |t|
  t.integer :questions_count
  t.integer :simple_questions_count
  t.integer :complex_questions_count
end
  1. All of them work
  2. None of them work
  3. Only questions_count work
  4. Only simple_questions_count and complex_questions_count

Which one? I am guessing the 3rd, but I want 4 more. If it's not 4, how do I make 4 work?

=== UPDATE ===

Here is an example:

id, user_id, question_content, type
1, 3, something, SimpleQuestion
2, 3, something, SimpleQuestion
3, 3, something, ComplexQuestion

So now I want:

user.questions_count # => 3
user.simple_questions_count # => 2
user.complex_questions_count # => 1

My question is, what's the basic behavior of :counter_cache => true and is it possible to apply on single table inheritance?


Solution

  • Looking through the source code where ":counter_cache" is implemented, it does not look like it supports the sort of counting you need. Fortunately, it is easy to roll your own here. Just update Question to track the counts manually, like so:

    class Question
      belongs_to :user
    
      after_create :increment_counts
      before_destroy :decrement_counts
    
      protected
    
      def increment_counts
        User.increment_counter :questions_count, user_id
        User.increment_counter "#{type.pluralize.underscore}_count", user_id
      end
    
      def decrement_counts
        User.decrement_counter :questions_count, user_id
        User.decrement_counter "#{type.pluralize.underscore}_count", user_id
      end
    end