Using build with a has_one association in rails

末鹿安然 提交于 2019-12-17 03:46:32

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!