after_update调用依赖于更改的关联方法

时间:2015-03-30 04:18:54

标签: ruby-on-rails callback

简介

我遇到了一个回调问题,该回调调用关联上的方法,但该方法取决于导致回调的更改。即使它在after_update中被调用,协会似乎也看不到变化。


方案

NerdProblemSet个,而ProblemSet属于Nerd

ProblemSet的status属性可以是:

  • "发现" - 找到要解决的问题
  • "求解" - 目前正在解决问题集
  • "解决" - 完成解决问题集

Nerd的working属性可以是:

  • true - ProblemSet中至少有一个的状态为"解决"
  • false - ProblemSet没有一个状态为"解决"

这是模型的样子:

class ProblemSet < ActiveRecord::Base
  belongs_to :nerd

  after_update :set_nerd_activity

  def set_nerd_activity
    if status_changed?
      self.nerd.set_working
    end
  end
end

class Nerd < ActiveRecord::Base
  has_many :problem_sets

  def set_working
    update_column(:working, solving_a_problem_set?)
  end

  def solving_a_problem_set?
    self.problem_sets.any? do |ps|
      ps.status == "solving"
    end
  end
end

问题

problemSet.status
=> "finding"

problemSet.update(status: "solving")

problemSet.nerd.working
=> false       # I'm expecting this to be true

我认为问题是nerd没有看到更改,就好像调用ProblemSet's时更改Nerd#set_status状态的数据库事务没有完全提交一样。

我的rspec测试Nerd只有ProblemSet次通过Nerd。但是他们适用于ProblemSet.reload。{/ p>

所以我想也许这是一个rspec的事情。

然后我在控制台中尝试了它,我仍然看到了这个问题。我也小心使用after_commit检查值是否已更新。

我尝试使用after_saveafter_update代替ProblemSets,但这会打断多个{{1}}对书呆子的测试。

知道发生了什么事吗?

1 个答案:

答案 0 :(得分:1)

这种方式应该正常工作,我在评论中提供的答案是有效的,因为你在查询关系之外的对象,这应该使它适用于你所拥有的旧代码。

class ProblemSet < ActiveRecord::Base
  belongs_to :nerd, inverse_of: :problem_sets
end

class Nerd < ActiveRecord::Base
  has_many :problem_sets, inverse_of: :nerd
end