Rails - проверка наличия ассоциации?

108

У меня есть модель A, которая имеет ассоциацию has_many с другой моделью B. У меня есть бизнес-требование, согласно которому для вставки в A требуется по крайней мере 1 связанная запись с B. Есть ли метод, который я могу вызвать, чтобы убедиться, что это правда, или мне нужно написать специальную проверку?

сказ
источник

Ответы:

168

Вы можете использовать validates_presence_of http://apidock.com/rails/ActiveModel/Validations/ClassMethods/validates_presence_of

class A < ActiveRecord::Base
  has_many :bs
  validates_presence_of :bs
end

или просто validates http://apidock.com/rails/ActiveModel/Validations/ClassMethods/validates

class A < ActiveRecord::Base
  has_many :bs
  validates :bs, :presence => true
end

Но есть ошибка с ним , если вы будете использовать accepts_nested_attributes_forс :allow_destroy => true: Вложенными моделями и родительской проверкой . В этой теме вы можете найти решение.

fl00r
источник
18

-------- Рельсы 4 ------------

Простой validates presenceсработал для меня

class Profile < ActiveRecord::Base
  belongs_to :user

  validates :user, presence: true
end

class User < ActiveRecord::Base
  has_one :profile
end

Таким образом, Profile.createтеперь не удастся. Я должен использовать user.create_profileили связать пользователя перед сохранением файла profile.

гексинпетер
источник
6

Вы можете проверить ассоциации с помощью validates_existence_of(это плагин):

Пример фрагмента из этой записи в блоге :

class Tagging < ActiveRecord::Base
  belongs_to :tag
  belongs_to :taggable, :polymorphic => true
  validates_existence_of :tag, :taggable

  belongs_to :user
  validates_existence_of :user, :allow_nil => true
end

В качестве альтернативы вы можете использовать validates_associated. Как отмечает Фейсал в комментариях под ответом, validates_associatedпроверяет, действителен ли связанный объект, путем запуска связанных проверок класса. Он не проверяет наличие. Также важно отметить, что пустая ассоциация считается действительной.

Спирос
источник
4

Если вы хотите убедиться, что ассоциация присутствует и гарантированно действительна, вам также необходимо использовать

class Transaction < ActiveRecord::Base
  belongs_to :bank

  validates_associated :bank
  validates :bank, presence: true
end
Сукирти Адига
источник
Было бы неплохо, если бы вы могли передать дополнительную опцию, которая validatesпонравится, valid: trueвместо того, чтобы звонить validates_associatedотдельно.
Джошуа Пинтер