Использование сборки с ассоциацией has_one в Rails
-
20-09-2019 - |
Вопрос
В этом примере я создаю user
без profile
, затем позже создайте profile
для этого пользователя. Я пытался использовать сборку с has_one
Ассоциация, но это взорвалось. Единственный способ, которым я вижу, что работа использует has_many
. Анкет А user
Предполагается иметь всего лишь максимум один profile
.
Я пробовал это. У меня есть:
class User < ActiveRecord::Base
has_one :profile
end
class Profile < ActiveRecord::Base
belongs_to :user
end
Но когда я сделаю:
user.build_profile
Я получаю ошибку:
ActiveRecord::StatementInvalid: Mysql::Error: Unknown column 'profiles.user_id' in 'where clause': SELECT * FROM `profiles` WHERE (`profiles`.user_id = 4) LIMIT 1
Есть ли способ в рельсах иметь 0 или 1 ассоциацию?
Решение
А build
Подпись метода отличается для has_one
а также has_many
ассоциации.
class User < ActiveRecord::Base
has_one :profile
has_many :messages
end
Синтаксис сборки для has_many
Ассоциация:
user.messages.build
Синтаксис сборки для has_one
Ассоциация:
user.build_profile # this will work
user.profile.build # this will throw error
Читать has_one
ассоциация документация Больше подробностей.
Другие советы
Посмотрите на сообщение об ошибке. Это говорит вам, что у вас нет необходимости в столбце user_id
в таблица профиля. Анкет Установка отношений в модели является лишь частью ответа.
Вам также необходимо создать миграцию, которая добавляет user_id
столбец в таблицу профиля. Rails ожидает, что это будет там, и если это не так, вы не можете получить доступ к профилю.
Для получения дополнительной информации, пожалуйста, посмотрите на эту ссылку:
В зависимости от варианта использования, может быть удобно обернуть метод и автоматически создавать ассоциацию, когда она не найдена.
old_profile = instance_method(:profile)
define_method(:profile) do
old_profile.bind(self).call || build_profile
end
Теперь звонит #profile
Метод либо вернет связанный профиль, либо создаст новый экземпляр.
источник:Когда Monkey Patching метод, можете ли вы вызвать переопределенный метод из новой реализации?
Это должно быть has_one
. Анкет Если build
не работает, вы можете просто использовать new
:
ModelName.new( :owner => @owner )
такой же как
@owner.model_names.build