如何验证两个关联对象是否具有相同的父对象?

时间:2013-08-14 17:31:05

标签: ruby-on-rails ruby ruby-on-rails-3

我有两个不同的对象,可以属于一个父对象。这些子对象也可以彼此属于(多对多)。确保彼此属于的子对象也属于同一父对象的最佳方法是什么。

作为我正在尝试做的一个示例,我有一个Kingdom,其中包含许多PeopleLandPeople模型会有一个自定义validate,如果有Land不匹配,我会检查每个相关的error.addkingdom_idLand模型具有类似的validate

这似乎有效,但在更新时允许记录保存'THIS IS AN ERROR'错误在people.errors,但是引发错误的Land已添加到{{ 1}}集合。

People

理想情况下,我希望错误取消记录更新。我还有另一种方法可以解决这个问题,还是我完全走错了方向?

kingdom = Kingdom.create
people  = People.create(:kingdom => kingdom)
land    = Land.create(:kingdom_id => 999)
people.lands << land
people.save
puts people.errors.inspect # @messages={:base=>["THIS IS AN ERROR"]
puts people.lands.inspect  # [#<Land id: 1...

1 个答案:

答案 0 :(得分:2)

首先,验证不会阻止将记录添加到模型的未加载集合中。它将阻止修订后的集合持久存储到数据库中。因此模型将处于无效状态,并以适当的错误进行标记。要查看此内容,您只需重新加载people对象。

您的逻辑中也有错误 - 即使找不到无效的kingdom_id,kingdom_match方法也永远不会返回true。你应该添加一行来解决这个问题:

def kingdom_match
  self.lands.each do |l|
    return false if l.kingdom_id != self.kingdom_id
  end
  true
end

您可以使此验证更简洁,并完全跳过kingdom_match方法:

def same_kingdom?
  if self.lands.any?{|l| l.kingdom_id != self.kingdom_id }
    errors.add(:base, 'THIS IS AN ERROR')
  end
end