似乎在rails中你可以在两个地方定义关联验证,或者在关联本身上定义:
class Child
belongs_to :parent, :validate => true
end
或作为验证回调:
class Child
belongs_to :parent
validates_associated :parent
end
这两种方法有什么区别?
测试差异
我认为也许前者会产生背压,并强制父母只有在孩子有效时才有效:
即。 (设置时:validate => true)
child.valid? # => false
child.parent.valid? # => also evaluates to false because of the :validate => true condition
# do whatever it takes to make the child valid again
#...
child.valid? # => true
child.parent.valid? # => true
然而,我测试了它,但这不会发生。那么两种方法之间有什么区别(如果有的话)?
答案 0 :(得分:40)
我不得不深入研究Rails(3.0.7)代码以找到一些差异。核心功能对我来说看起来是一样的 - 他们似乎都在相关记录上调用valid?
。
我发现的主要区别仅在使用:autosave
功能时或者在销毁关联对象或将其标记为销毁时才会显示。例如,我有:
class AbsentDate < ActiveRecord::Base
belongs_to :user, :autosave => true, :validate => true
end
我看到以下行为:
user = User.new(:username => "Jimmy")
user.valid? # => true
ad = AbsentDate.new(:user => user)
user.username = nil
user.valid? # => false
ad.valid? # => false
ad.errors.full_messages # => ["User username cannot be empty"]
ad.user.mark_for_destruction
ad.valid? # => true
请注意,标记用户进行销毁会导致有效的AbsentDate。另请注意,只有一条错误消息。现在考虑这种情况:
class AbsentDate < ActiveRecord::Base
belongs_to :user, :autosave => true
validates_associated :user
end
这就是我看到的情况:
user = User.new(:username => "Jimmy")
user.valid? # => true
ad = AbsentDate.new(:user => user)
user.username = nil
user.valid? # => false
ad.valid? # => false
ad.errors.full_messages # => ["User username cannot be empty", "User is invalid"]
ad.user.mark_for_destruction
ad.valid? # => false
这次有两条错误消息,即使用户已被标记为销毁,AbsentDate仍然是假的。我通过调用destroy而不是mark_for_destruction来复制这些结果。
最后一件事:如果你使用validates_associated
,你会得到几个你不会选择的选项(:if
,:unless
,:on
,:message
)如果您使用belongs_to
上的标记,则会有。