假设:
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会返回它自己的错误(上面代码块中的错误),但如果我的记录与自身相关联,我会得到一个大问题。即使我停止节点验证它的相关孩子/父母,我仍然会收到错误。
只要我试图保存ITSELF的记录有错误,然后Rails用上面的错误替换我的422。这简直太糟糕了。我想要一个JSON响应错误,所以我的客户端知道到底出了什么问题。
我发现很难相信没有其他人遇到过这个问题,我错过了什么吗?
答案 0 :(得分:0)
您是否在Node
模型中调用了验证器?如果是这样,上面的代码应该工作。
我试过了,
class Node < ActiveRecord::Base
has_many :children, class_name: :Node, foreign_key: :parent_id
belongs_to :parent, class_name: :Node, foreign_key: :parent_id
validates_with NodeParentValidator
end
验证器代码相同。这是在控制台中测试的结果。
答案 1 :(得分:0)
我认为您必须向初始节点添加错误:
def validate(node)
@node = node
unless validate_recursive(node)
@node.errors[:parent_id] << "Node can't be it's own parent"
end
end