问题
In this example, I create a user
with no profile
, then later on create a profile
for that user. I tried using build with a has_one
association but that blew up. The only way I see this working is using has_many
. The user
is supposed to only have at most one profile
.
I have been trying this. I have:
class User < ActiveRecord::Base
has_one :profile
end
class Profile < ActiveRecord::Base
belongs_to :user
end
But when I do:
user.build_profile
I get the error:
ActiveRecord::StatementInvalid: Mysql::Error: Unknown column 'profiles.user_id' in 'where clause': SELECT * FROM `profiles` WHERE (`profiles`.user_id = 4) LIMIT 1
Is there a way in rails to have 0 or 1 association?
回答1:
The build
method signature is different for has_one
and has_many
associations.
class User < ActiveRecord::Base
has_one :profile
has_many :messages
end
The build syntax for has_many
association:
user.messages.build
The build syntax for has_one
association:
user.build_profile # this will work
user.profile.build # this will throw error
Read the has_one
association documentation for more details.
回答2:
Take a good look at the error message. It is telling you that you do not have required column user_id
in the profile table.
Setting the relationships in the model is only part of the answer.
You also need to create a migration that adds the user_id
column to the profile table.
Rails expects this to be there and if it is not you cannot access the profile.
For more information please take a look at this link:
Association Basics
回答3:
Depending on the use case, it can be convenient to wrap the method and automatically build the association when not found.
old_profile = instance_method(:profile)
define_method(:profile) do
old_profile.bind(self).call || build_profile
end
now calling the #profile
method will either return the associated profile or build a new instance.
source: When monkey patching a method, can you call the overridden method from the new implementation?
回答4:
It should be a has_one
. If build
isn't working, you can just use new
:
ModelName.new( :owner => @owner )
is the same as
@owner.model_names.build
来源:https://stackoverflow.com/questions/2472982/using-build-with-a-has-one-association-in-rails