def Node
belongs_to :parent, class_name: :Node
has_many :children, class_name: :Node, foreign_key: :parent_id
end
我想创建一个验证,以确保一个节点不能被它自己的父母,或者是父母的父母等
我得到这个:
# Custom validator to check if the Parent Node is related to the current node. Avoids that ugly self-association loop.
#
class NodeParentValidator < ActiveModel::Validator
def validate(node)
@node = node
unless validate_recursive(node)
node.errors[:parent_id] << "Node can't be it's own parent"
end
end
def validate_recursive(node)
# If the validating node doesn't have a parent, we return true because we're either facing a node that doesn't have any parent
# or we got to the point that we need to stop the recursive loop.
return true if node.parent.nil?
# If the validating node is the same as the current "parent", we found the self-association loop. This is bad.
return false if @node.id == node.parent_id
# While we don't get to the end of the association, keep jumping.
return false unless validate_recursive(node.parent)
return true
end
end
它完全有效!实际上这是问题。它是否有效?当Rails调用assign_attributes方法时,我得到了422,但它没有我的验证!相反,我得到一个丑陋的HTML验证错误是这样的:
ActiveRecord::RecordNotSaved (Failed to replace children because one or more of the new records could not be saved.)
所以,如果Rails可以救不了它的相关记录的Rails返回它自己的错误(一个在上面的代码块),但如果我的记录是相关联本身,我遇到了很大的问题。即使我阻止Node验证其相关的孩子/父母,我仍然会遇到错误。
只要我试图自救记录有错误,那么Rails的替换我422上面的错误。那简直太糟糕了。我想要一个JSON响应错误,以便我的客户知道究竟出了什么问题。
我很难相信没有其他人遇到这个问题,我失去的东西吗?
我发现它有点难以跟随你说在过去的3段什么,因为您使用代词“这”指很多不同的东西。自定义验证器的逻辑看起来对我来说很好,这取决于你所说的你想做什么。如果您的记录与自身相关联,那么为什么会出现错误?你说这应该会发生,对吧?或者,您的问题仅仅是您希望验证者的错误消息显示在日志中,而不是实际获得的错误消息? –
对不起,晚上的时间已经很晚了,我想我在那时开始讨厌代词。希望这个问题现在更有意义。 问题出在什么错误,我想从我的验证中得到的错误,而不是Rails的通用ActiveRecord :: RecordNotSaved错误。防止关联被持久化是一回事,但是让记录返回我自己的错误是另一回事:“节点不能是它自己的父母”。 – Harbinger
哦,所以你不能在你的控制器中添加一个条件,如果创建失败,它会调用模型中的errors方法并返回JSON响应?通过这种方式,您明确告诉Rails您希望JSON响应消息是什么?无论如何,Rails可能会感到困惑,因为如果记录引用自身,技术上仍然试图创建子关联,并且它通过验证该子关联失败,因此消息必须是模糊的,因为它是has_many关联,并且即使有多个错误也必须有意义。 –