2012-11-22 34 views
0

运行回调时,我有2个型号:为什么我得到错误堆栈层次过深after_save的

  • GeneralExam有许多TopicQuestion
  • TopicQuestion属于GeneralExam,belongs_to的主题

这是在列两种型号:

  • 一般检查:名称,说明,number_question
  • TopicQuestion:general_exam_id,topic_id,number_question

我想计算的一般考试的问题总数,由TopicQuestion每个主题的加number_question。所以我写这样的方法:

class GeneralExam < ActiveRecord::Base 

    has_many :topic_questions, dependent: :destroy 

    validates :number_question, numericality: { only_integer: true, greater_than: 0 }, on: :save 

    after_save :calc_number_question 

    private 

    def calc_number_question 
    number_question = 0 
    self.topic_questions.each do |tq| 
     number_question += tq.number_question 
    end 
    self.number_question = number_question 
    self.save 
    end 
end 

但是,当我提出,我得到错误:

SystemStackError in GeneralExamsController#create 
stack level too deep 

这是我的参数:

{"utf8"=>"✓", 
"authenticity_token"=>"VyojDMOltc5wOJMDf4gtDM6lEk6soTZl/EaY9qrCRyY=", 
"general_exam"=>{"course_id"=>"1", 
"name"=>"dada", 
"description"=>"dada", 
"semester_id"=>"1", 
"duration"=>"1", 
"topic_questions_attributes"=>{"0"=>{"_destroy"=>"false", 
"topic_id"=>"15", 
"number_question"=>"15"}, 
"1"=>{"_destroy"=>"false", 
"topic_id"=>"13", 
"number_question"=>"6"}, 
"2"=>{"_destroy"=>"false", 
"topic_id"=>"Choose a topic", 
"number_question"=>""}, 
"3"=>{"_destroy"=>"false", 
"topic_id"=>"Choose a topic", 
"number_question"=>""}, 
"4"=>{"_destroy"=>"false", 
"topic_id"=>"Choose a topic", 
"number_question"=>""}}}, 
"commit"=>"Create General exam"} 

什么我错了吗?

回答

11

您最后称为self.save。它正在启动另一个after_save回调。

如果您的轨道版本是3.2.1或更高版本可以使用

update_column :number_question, number_question 

跳过回调。

offtopic:

你可以把它改写

number_question = 0 
self.topic_questions.each do |tq| 
    number_question += tq.number_question 
end 

number_question = self.topic_questions.inject(0) { |sum, tq| sum + tq.number_question } 
+1

谢谢,我发现了另一种计算方法,我使用sum方法:'number_question = TopicQuestion.sum(:number_question,conditions:{general_exam_id:self.id})' – Thanh

+0

'update_column'在rails 3.1及更高版本中工作。我只是用它来解决类似的问题。 – emkman

0

使用after_commit作为回调。它会正常工作,因为它不会循环。