Rails - как я могу проверить существование строки, на которую ссылается внешний ключ
Учитывая, что "Rails Way", похоже, не использует ограничения внешнего ключа, я ищу альтернативу, которая позволит мне проверить, что строка, связанная с внешними ключами, действительно существует в TableA, прежде чем я сохраню объект в TableB с table_a_id.
Единственный ресурс, который я нашел, чтобы сделать это до сих пор (не могу найти ссылку на сообщение в блоге, о котором он упоминал, был датирован 2007 годом), похоже, не совместим с Rails 3.2, так что кто-нибудь может предложить способ сделать это?
В настоящее время я смотрю на создание валидатора, чтобы вручную назначать соответствующие атрибуты в моих моделях, но я не могу решить, как это сделать с помощью validate_each (объект, атрибут, значение).
Ответы
Ответ 1
Существует плагин, который поможет вам в этом для ассоциаций принадлежать_to: Проверяет существование. Но, может быть, вы можете добавить свою собственную проверку? Что-то вроде этого:
# Assuming your foreign key is user_id (which references the table User)
validate :user_id_exists
def user_id_exists
return false if User.find_by_id(self.user_id).nil?
end
Ответ 2
просто используйте, как показано ниже,
validates :user, presence: true
Он автоматически проверяет наличие записи пользователя в db.
Ответ 3
У меня были проблемы с этим фрагментом кода:
return false if User.find(self.user_id).nil?
Мне пришлось поймать исключение ActiveRecord, если не найдено подходящей записи. nil? не работает, когда запись не найдена; исключение создается до выполнения nil?.
# Assuming your foreign key is user_id (which references the table User)
validate :user_id_exists
def user_id_exists
begin
User.find(self.user_id)
rescue ActiveRecord::RecordNotFound
errors.add(:user_id, "user_id foreign key must exist")
false
end
end
Это полезно, если вы используете недопустимые? утверждения в модульных тестах.
request.user_id = unknown
assert request.invalid?
request.user_id = 1
assert request.valid?
Ответ 4
Обратите внимание, что с Rails 3.2, validates_presence_of работает точно так, как вы хотите, в этом случае, и вам не нужно создавать сложную структуру, такую как вышеупомянутые ответы, или даже использовать хороший validates_existence_of gem.
Ответ 5
Мне не нравятся исключения. Я решил эту проблему, выполнив следующие действия:
class Foo < ActiveRecord::Base
validate :bar_exists
protected
def bar_exists
if !User.where(bar_id: self.bar_id).exists? then
errors.add(:bar_id, 'A valid bar_id is valid.')
end
end
end
Ответ 6
Вам нужно указать опцию inverse_of
и подтвердить, что оно истинно.
В Руководство по проверке активной записи:
Чтобы проверить связанные записи, присутствие которых необходимо, вы должны указать опцию : inverse_of для ассоциации