after_update 调用依赖于变化的关联方法

after_update calls association's method that depends on the change

简介

我在调用关联方法的回调时遇到问题,但该方法取决于导致回调的更改。即使在 after_update.

中调用关联,它似乎也看不到变化

场景

一个Nerd有很多个ProblemSet,一个ProblemSet属于一个Nerd

ProblemSet 有一个 status 属性,可以是:

书呆子有一个 working 属性,可以是:


这是模型的样子:

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 没有看到变化,就好像调用 Nerd#set_status 时更改 ProblemSet's 状态的数据库事务没有完全提交。

我的 rspec 测试 Nerd 和一个 ProblemSet 没有通过。但它们确实适用于 Nerd 和多个 ProblemSet.

所以我认为这可能是 rspec 的事情。

然后我在控制台中尝试了它,但我仍然看到了问题。我也很小心地使用 .reload 来检查值是否已更新。

我试过使用 after_commitafter_save 而不是 after_update 但这打破了对书呆子的多个 ProblemSets 的测试。

知道发生了什么吗?

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

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

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