ruby-on-rails - 在 Rails 4 中验证循环关联的正确方法是什么?

标签 ruby-on-rails ruby validation ruby-on-rails-4 activerecord

给定:

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 会返回它自己的错误(上面代码块中的错误),但如果我的记录与其自身相关联,我就会遇到一个大问题。即使我阻止节点验证其关联的 child / parent ,我仍然会收到错误消息。

只要我试图保存的记录 ITSELF 有错误,Rails 就会用上面的错误替换我的 422。那真是太糟糕了。我想要一个 JSON 响应错误,以便我的客户知道到底出了什么问题。

我很难相信没有其他人遇到过这个问题,我是不是漏掉了什么?

最佳答案

你在Node模型中调用过validator了吗?如果是这样,上面的代码应该可以工作。

我试过了,

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

验证器代码相同。这是在控制台中测试的结果。

Here is the result of the testing in console

关于ruby-on-rails - 在 Rails 4 中验证循环关联的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32130989/

相关文章:

c# - FluentValidation 和服务器+客户端远程验证器

java - 如何使用 java 正则表达式验证字符串?

regex - 检查字符串是否包含 1 个数字、1 个字母且长度在 5-15 个字符之间

ruby-on-rails - 如何在现有的 Rails 引擎中生成虚拟应用程序

ruby - 如何从数组中获取哈希值

ruby-on-rails - 如何让 Capistrano 3 使用 RVM ruby​​?

ruby-on-rails - Ruby on Rails has_many 多态

mysql - 使用 id 从表中检索值

ruby-on-rails - 用户回形针重命名上传的文件

ruby-on-rails - 即使在成功安装后也会出现恼人的 libv8 错误