Когда использовать «validates_associated» v. «Assign_to: parent,: validate => true» - PullRequest
28 голосов
/ 18 июня 2011

Кажется, что в рельсах вы можете определить валидацию ассоциации в двух местах, либо в самой ассоциации:

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

Однако я проверил это, и этого не происходит. Так в чем же разница (если есть) между двумя методами?

1 Ответ

40 голосов
/ 19 июня 2011

Мне пришлось копаться в коде 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 все еще имеет значение false, даже если его пользователь был помечен для уничтожения. Мне удалось воспроизвести эти результаты, вызвав уничтожение вместо mark_for_destruction.

И последнее: если вы используете validates_associated, вы получите несколько опций (:if, :unless, :on, :message), которых у вас не будет, если вы используете флаг на belongs_to .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...