我如何可以验证的has_many关系没有改变 [英] How can I validate that has_many relations are not changed
问题描述
我有一个相当典型的订单的模式,即的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 thebefore_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屋!