在 Rails 中,关联的 objects 是如何 up-to-date 的?

In Rails, how does one associated objects are up-to-date?

考虑:

class Parent < ActiveRecord::Base
  has_many :blue_children
  has_many :red_children
end

class BlueChild < ActiveRecord::Base
  belongs_to :parent
end

class RedChild < ActiveRecord::Base
  belongs_to :parent

  validate :parent_cannot_have_blue_children

  def parent_cannot_have_blue_children
    unless parent.blue_children.empty?
      errors.add(:parent, 'has blue children')
    end
  end
end

对于这样的代码:

def test
  p = Parent.create!
  # Much time passes, during which, perhaps, some far-off process adds
  # a blue child to p.
  p.red_children.create!
end

存在验证者看到 out-of-date 版本 parent 的风险。特别是,即使验证器中似乎没有蓝色 children,也可能有一个。我检查了 SQL 日志以确认没有查询重新加载 parent 或来自验证器的 blue_children 关联。

我可以想出几种方法来解决这个问题:

目前,我倾向于在数据库中维护一个计数器。有没有更好的方法?

您可以在验证中使用 exists?:它将触发一个新的 SQL 请求来检查蓝色 children 是否存在:

class RedChild < ActiveRecord::Base
  belongs_to :parent

  validate :parent_cannot_have_blue_children

  def parent_cannot_have_blue_children
    if BlueChild.exists?(parent: self.parent)
      errors.add(:parent, 'has blue children')
    end
  end
end

这样验证总是最新的。