0

当我注释掉我的after_save回电时,我的 ActiveRecord 关联工作得很好。在 Rails 控制台中,您会看到:

> @report = Report.create :name => "foo"
=> #<Report id: 9, name: "foo", created_at: "2013-03-05 09:51:55", updated_at: "2013-03-05 09:51:55"> 
> @question = @report.questions.create :description => "bar"
=> #<Question id: 18, standard_id: nil, description: "bar", element_id: nil, condition_id: nil, blueprint_name: nil, blueprint_url: nil, created_at: "2013-03-05 09:52:32", updated_at: "2013-03-05 09:52:32", additive: false, instructions: nil> 
> @report.questions
=> [#<Question id: 18, standard_id: nil, description: "bar", element_id: nil, condition_id: nil, blueprint_name: nil, blueprint_url: nil, created_at: "2013-03-05 09:52:32", updated_at: "2013-03-05 09:52:32", additive: false, instructions: nil>] 
> @question.reports
=> [#<Report id: 9, name: "foo", created_at: "2013-03-05 09:51:55", updated_at: "2013-03-05 09:51:55">]

但是,当我将以下after_save回调添加到时,关联停止工作question.rb

  def create_matching_surveys
    self.reports.each do |report|
      report.reviews.each do |review|
        review.competitors.each do |competitor|
          competitor.surveys.find_or_create_by_question_id(self.id)
        end
      end
    end
  end

然后,在 Rails 控制台中,您将获得:

> @report = Report.create :name => "foo"
=> #<Report id: 13, name: "foo", created_at: "2013-03-05 10:20:51", updated_at: "2013-03-05 10:20:51">
> @question = @report.questions.create :description => "bar"
=> #<Question id: 24, standard_id: nil, description: "bar", element_id: nil, condition_id: nil, blueprint_name: nil, blueprint_url: nil, created_at: "2013-03-05 10:21:02", updated_at: "2013-03-05 10:21:02", additive: false, instructions: nil> 
> @report.questions
=> [#<Question id: 24, standard_id: nil, description: "bar", element_id: nil, condition_id: nil, blueprint_name: nil, blueprint_url: nil, created_at: "2013-03-05 10:21:02", updated_at: "2013-03-05 10:21:02", additive: false, instructions: nil>] 
> @question.reports
=> [] 

无论报告是否包含有竞争对手的评论,都会发生这种情况。

奇怪的是我认为回调是在问题被保存后发生的?所以按照权利,协会也应该在这一切发生之前保存,对吧?

我如何解决它?

更新

我想我必须在对象生命周期的正确位置调用回调,但我找不到那个位置。这就是我认为的原因:

> @report = Report.create :name => "foo"
=> #<Report id: 20, name: "foo", created_at: "2013-03-05 12:29:35", updated_at: "2013-03-05 12:29:35"> 
> @question = @report.questions.create :description => "bar"
=> #<Question id: 31, standard_id: nil, description: "bar", element_id: nil, condition_id: nil, blueprint_name: nil, blueprint_url: nil, created_at: "2013-03-05 12:30:14", updated_at: "2013-03-05 12:30:14", additive: false, instructions: nil> 
> @question.reports
 => [] 
> @question.update_attributes :description => "foo"
=> true 
> @question.reports
=> [#<Report id: 20, name: "foo", created_at: "2013-03-05 12:29:35", updated_at: "2013-03-05 12:29:35">] 

顺便说一句,该方法现在在 question_observer.rb 中:

class QuestionObserver < ActiveRecord::Observer

  def after_save(model)
    model.reload
    model.reports.reload
    model.reports.each do |report|
      report.reviews.each do |review|
        review.competitors.each do |competitor|
          competitor.surveys.find_or_create_by_question_id(model.id)
        end
      end
    end
    return true
  end

end
4

1 回答 1

0

after_commit答案是使用Rails 3 引入的一个简洁的新回调钩子。

请参阅http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html#method-i-after_commit

唯一的问题是after_commit不能“开箱即用”地使用事务性装置,但是有很多解决方案,我发现这个对我来说效果很好:https: //supportbee.com/devblog/2012/01 /14/testing-after_commitafter_transaction-with-rspec/

于 2013-03-06T02:54:11.767 回答