当使用" validates_associated" V" belongs_to的:父母,:验证=>真QUOT;父母、validates_associated、QU

2023-09-09 22:02:32 作者:别让梦想只是梦想

看来,在轨可以在两个地方定义的关联验证,无论是对联想本身:

It seems that in rails you can define association validations in two places, either on the association itself:

Class Child

  belongs_to :parent, :validate => true

end

或者作为验证回调:

Or as a validation callback:

Class Child

  belongs_to :parent

  validates_associated :parent

end

这两种方法之间的区别是什么?

What is the difference between these two methods?

测试的区别

我想,也许前者创建了一个回pressure并强制父是唯一有效的,如果孩子是有效的:

I thought that maybe the former creates a backpressure and enforces that the parent is only valid if the child is valid:

即。 (设定值:验证=> TRUE)

i.e. (when setting :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

不过我测试了它,并不会发生这种情况。那么,有什么区别(如果有的话),这两种方法之间?

However I tested it and this doesn't happen. So what's the difference (if any) between the two methods?

推荐答案

我不得不深入到Rails的(3.0.7)code找到一些差异。核心功能看起来是一样的我? - 他们似乎都打电话有效在相关结果

I had to dig into the Rails (3.0.7) code to find some differences. The core functionality looks the same to me -- they both seem to call valid? on the associated record(s).

关键的区别,我也只能用时,发现显示:自动保存功能或者毁坏任何关联的对象,或将其标记为破坏。例如,我有:

The key differences that I did find only appear when using the :autosave feature or when either destroying the associated object or marking it for destruction. For example, I have:

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。还要注意的是,只有一个错误消息。现在考虑这种情况下:

Note that marking the user for destruction resulted in a valid AbsentDate. Also note that there is only one error message. Now consider this case:

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是,尽管其用户已被标记为毁灭还是假的。我可以通过调用破坏,而不是mark_for_destruction复制这些结果。

Two error messages this time, and the AbsentDate is still false even though its user has been marked for destruction. I was able to replicate these results by calling destroy instead of mark_for_destruction.

最后一件事:如果你使用 validates_associated ,你得到几个选项(:如果:除非:在:消息),你不会有如果您使用标记belongs_to的

One last thing: if you use validates_associated, you get several options (:if, :unless, :on, :message) that you won't have if you use the flag on belongs_to.