Использование сборки с ассоциацией has_one в рельсах
В этом примере я создаю 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 ассоциацию?
Ответы
Ответ 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
ассоциацию .
Ответ 2
Взгляните на сообщение об ошибке. Он говорит вам, что в таблице профиля не требуется столбца user_id
.
Установка отношений в модели является лишь частью ответа.
Вам также необходимо создать перенос, который добавляет столбец user_id
в таблицу профилей.
Rails ожидает, что это будет там, и если это не так, вы не сможете получить доступ к профилю.
Для получения дополнительной информации перейдите по этой ссылке:
Основы ассоциации
Ответ 3
В зависимости от варианта использования может быть удобно обернуть метод и автоматически построить ассоциацию, если он не найден.
old_profile = instance_method(:profile)
define_method(:profile) do
old_profile.bind(self).call || build_profile
end
теперь вызов метода #profile
приведет либо к возврату связанного профиля, либо к созданию нового экземпляра.
Источник:
Когда обезьяна исправляет метод, вы можете вызвать переопределенный метод из новой реализации?
Ответ 4
Он должен быть has_one
. Если build
не работает, вы можете просто использовать new
:
ModelName.new( :owner => @owner )
совпадает с
@owner.model_names.build