是否有可用于所有关联记录的特定属性的验证?
Is there a validation I can use for a specific attribute on all associated records?
我有一个 Question
has_many :answers
(就像 SO)。我还希望每个问题只有 1 个 accepted_answer
,所以我只是向 Answer
模型添加了一个 :accepted
属性,它只是一个布尔值。
现在,为了让我的问题得到公认的答案,我在我的模型上编写了一个方法来执行此操作:
def accepted_answer
answers.where(accepted: true)
end
这让我可以做 question.accepted_answer
并且它 returns 一个 ActiveRelation 对象,就像你期望的那样。
没什么特别的。简单有效。
但是,我想确保的是,在任何时刻,每个问题都只能有一个 accepted: true
的答案。
解决这个问题的最佳方法是什么?
我考虑过使用验证器,但找不到以这种方式处理关联对象的验证器。有些有一些有趣的点点滴滴,但我不能把所有的部分都放在一起。比如presence is interesting as is absence and validates_with(不过最后这个感觉太重了)
建议?
最好的方法很可能是使用 after_add
回调(例如 here),这将通过 update_all 将所有现有的 accepted
记录设置为 false以及接受设置为 true 的最新答案。这完全取决于你的逻辑。
您还可以使用一些其他回调,例如 before_save、before_update 等具有类似功能的回调,具体取决于您的应用程序细节。
它不会退出验证,但会有效地维护您的模型所需的状态。此外,验证的目的是在某些内容无效时向您发出警告,但我猜您想在没有此类失败的情况下保存您的对象,并且只执行一个接受的答案。
如果您想在第一个答案被接受后停止添加答案,请告诉我。在这种情况下,它需要不同的功能。
我有一个 Question
has_many :answers
(就像 SO)。我还希望每个问题只有 1 个 accepted_answer
,所以我只是向 Answer
模型添加了一个 :accepted
属性,它只是一个布尔值。
现在,为了让我的问题得到公认的答案,我在我的模型上编写了一个方法来执行此操作:
def accepted_answer
answers.where(accepted: true)
end
这让我可以做 question.accepted_answer
并且它 returns 一个 ActiveRelation 对象,就像你期望的那样。
没什么特别的。简单有效。
但是,我想确保的是,在任何时刻,每个问题都只能有一个 accepted: true
的答案。
解决这个问题的最佳方法是什么?
我考虑过使用验证器,但找不到以这种方式处理关联对象的验证器。有些有一些有趣的点点滴滴,但我不能把所有的部分都放在一起。比如presence is interesting as is absence and validates_with(不过最后这个感觉太重了)
建议?
最好的方法很可能是使用 after_add
回调(例如 here),这将通过 update_all 将所有现有的 accepted
记录设置为 false以及接受设置为 true 的最新答案。这完全取决于你的逻辑。
您还可以使用一些其他回调,例如 before_save、before_update 等具有类似功能的回调,具体取决于您的应用程序细节。
它不会退出验证,但会有效地维护您的模型所需的状态。此外,验证的目的是在某些内容无效时向您发出警告,但我猜您想在没有此类失败的情况下保存您的对象,并且只执行一个接受的答案。
如果您想在第一个答案被接受后停止添加答案,请告诉我。在这种情况下,它需要不同的功能。