【问题标题】:ActiveRecord presence validation for has_many through assosiation通过关联对 has_many 进行 ActiveRecord 存在验证
【发布时间】:2015-07-30 14:22:00
【问题描述】:

我遇到了 Rails 验证问题,我将在此处尝试解释。

想象一下我有这样的场景:

Parent 有很多 ParentChild, Child有很多ParentChild, ParentChild 属于 Parent 和 Child, 此外,父母可以是活跃的或不活跃的。

我需要在活跃的父母身上验证孩子的存在。为此,我编写了以下代码:

validates :child, presence: { message: "can't be blank on active parents" }, if: -> (parent) { parent.active? }

而且它确实有效。

假设我有这个 Parent 与它关联的 4 个孩子,我从中删除了这 4 个关联的孩子。然后验证启动并将错误消息添加到父模型,但不会阻止删除关联的子模型。

基本上,相关的子级将被删除并进行验证。

我还尝试使用自定义验证甚至是 before_validation 回调来手动检查子项的删除,但似乎没有任何效果。

如有任何帮助,我们将不胜感激。

【问题讨论】:

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


    【解决方案1】:

    你如何在ParentChild模型中添加before_destroy回调

    ...
      before_destroy :check_if_last
    ...
    
    private
    
    def check_if_last
      if parent.active? && parent.children.count == 1
        errors.add(:child, "can't be blank on active parents")       
      end
    end
    

    【讨论】:

    • 是的,我也试过这个,不仅它根本不起作用,而且即使它起作用,行为也会有点奇怪。想象一下,您一次删除所有四个孩子,验证会留下一个“随机”,并且会向用户显示错误。在验证失败的情况下,我宁愿回滚整个删除操作。
    【解决方案2】:

    既然你只想破坏关系,你可以挂钩关系模型本身。只需注意返回 false。为了通过回调回滚事务,您需要返回一个 false,是的,一个 false 不是一个 falsy 值,否则它仍然会提交。

      before_destroy :last_of_active_parent?
    
      private
    
      def last_of_active_parent?
        if parent.active? && parent.children.count == 1
          errors.add(:parent, "which is active can't lose the last child") 
          false      
        end
      end
    

    【讨论】:

    • 不,我正在破坏关系,而不是 Child 本身。所以在这种情况下不会调用 Child 上的 before_destroy。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-01
    • 1970-01-01
    相关资源
    最近更新 更多