Reputation: 31
For example, I have three model user, question and answer, and the relationship between them are:
class User < ActiveRecord::Base
has_many :answers
has_many :questions
end
class Question < ActiveRecord::Base
has_many :answers, :dependent => :destroy
belongs_to :user, :counter_cache => true
end
class Answer < ActiveRecord::Base
belongs_to :user, :counter_cache => true
belongs_to :question, :counter_cache => true
end
Then when i want to destroy a question(with 1000 answers), these will happen: The answers will destroy one by one and will update the counter in the user model, even the counter in the question i want to destroy, and which will take a long time to do the counter update.
my question is how to make it faster?
Upvotes: 1
Views: 2027
Reputation: 31
I got my own solution like this:
step 1: remove the dependent destroy, which will call for counter update before destroy itself.
step 2: add my own before_destroy, like this
before_destroy :delete_dependents
and use delete_all function to delete without call any before_destroy, then call reset_counters function to reset the counter in User model.
full codes of class question:
class Question < ActiveRecord::Base
has_many :answers
has_many :answer_users, :through => :answers, :source => :user, :uniq => true
belongs_to :user, :counter_cache => true
before_destroy :delete_dependents
private
def delete_dependents
answer_user_ids = self.answer_user_ids # eager loading for store the answer users id
Answer.delete_all(:question_id => self.id)
answer_user_ids.each do |u_id|
User.reset_counters u_id, :answers
end
end
end
PS: If there are too many counters need to be reset, you might need a background job to work it out.
Upvotes: 1