我如何可以验证的has_many关系没有改变 [英] How can I validate that has_many relations are not changed

查看:143
本文介绍了我如何可以验证的has_many关系没有改变的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个相当典型的订单的模式,即的has_many

I have an fairly typical Order model, that has_many Lines

class Order < ActiveRecord::Base
  has_many :lines
  validates_associated :lines

一旦整理完毕,它应该无法更改任何属性或相关行(虽然不完成,您可以更改状态)。

Once the order is completed, it should not be possible to change any attributes, or related lines (though you can change the status to not completed).

  validate do
    if completed_at.nil? == false && completed_at_was.nil? == false
      errors.add(:base, "You can't change once complete")
    end
  end

这工作得很好,的的,如果你要添加,删除或更改相关的,然后这是不是pvented $ P $。

This works fine, but, if you add to, remove, or change the associated Lines, then this isn't prevented.

在我的订单的模式,我有以下验证:

In my Line model, I have the following validation:

validate do
  if order && order.completed_at.nil? == false
    errors.add(:base, "Cannot change once order completed.")
  end
end

这成功地停在已完成的订单行被修改,和prevents行被添加到已完成的订单。

This successfully stops lines in a completed order being modified, and prevents a line being added to a completed order.

所以,我也需要prevent线被运出的已完成的订单。我在模式尝试这样的:

So I need to also prevent lines being taken out of a completed order. I tried this in the Line model:

validate do
  if order_id_was.nil? == false
    if Order.find(order_id_was).completed_at.nil? == false
      errors.add(:base, "Cannot change once order completed.")
    end
  end
end

这工作得很好,以prevent一个订单被取出来的的修改订单的时候直接订单。然而,当你正在编辑在订单并删除订单,验证从来没有运行,因为它已经被从订单删除。

This works fine to prevent a Line being taken out of an Order when modifying the Line directly. However when you are editing the Order and remove a Line, the validation never runs, as it has already been removed from the Order.

所以......总之,我如何可以验证订单不改变,并且不添加或者删除相关?

So... in short, how can I validate that the Lines associated with an Order do not change, and are not added to or removed?

我想我失去了一些东西明显。

I'm thinking I'm missing something obvious.

推荐答案

的ActiveRecord ::协会 ,你会看到,有一些回调,你可以添加到您的的has_many 定义:

  • before_add
  • after_add
  • before_remove
  • after_remove
  • before_add
  • after_add
  • before_remove
  • after_remove

另外从同一个文档:

如果有任何的 before_add 回调抛出一个异常,对象不会被添加到集合。同样的,在 before_remove 回调;如果有异常被抛出的对象不会被删除。

Should any of the before_add callbacks throw an exception, the object does not get added to the collection. Same with the before_remove callbacks; if an exception is thrown the object doesn't get removed.

也许你可以添加一个回调方法 before_add before_remove ,使确保次序不是冻结,抛出一个异常,如果是不允许的。

Perhaps you can add a callback method to before_add and before_remove that makes sure the order isn't frozen and throws an exception if it's not allowed.

has_many :lines,
         before_add:    :validate_editable!,
         before_remove: :validate_editable!

private

def validate_editable!(line)
  # Define the logic of how `editable?` works based on your requirements
  raise ActiveRecord::RecordNotSaved unless editable?(line)
end

另一件值得尝试将添加一个验证错误,并返回 validate_editable_lines!如果您的验证测试失败。如果这样的作品,我建议你改变航向的方法名 validate_editable_lines (SANS 砰的一声)。 :)

Another thing worth trying would be to add a validation error and return false within validate_editable_lines! if your validation test fails. If that works, I'd recommend changing the method name to validate_editable_lines (sans ! bang), of course. :)

这篇关于我如何可以验证的has_many关系没有改变的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆