Rails:在Rails中使用带有has_one关联的build


143

在此示例中,我创建了一个userno profile,然后稍后profile为该用户创建一个。我尝试将build与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

Rails中有没有一种方法可以使0或1有关联?


您到底尝试了什么?可以请您发布一些代码吗?
Ju Nogueira 2010年

Answers:


359

build方法的签名是不同 has_onehas_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协会文档以了解更多详细信息。


28
has_one的不同语法总是让我失望...该死!
银河

11
有趣的是,这里获得最高评价和接受的答案是回答与操作员提出的问题不同的问题。
Ajedi32

据说,如果用户属于个人资料(指用户表中有其表foreign_key PROFILE_ID),那么还建设上面,即但仅在新的行动提到的用户配置文件将工作user.build_profile 的编辑user.build_profile if user.profile.nil? ,如果你想建立的个人资料,同时创建用户然后写accepts_nested_attributes_for :profile这用户模型。并以创建用户的形式编写<%= f.simple_fields_for :profile do |p| %>并继续。
2015年

但是为什么为has_one或has_many保留了这种不同的行为?我认为并期望在设计时会有一些原因。
好奇的

@ Ajedi32答案与问题的标题匹配,但与正文不匹配。鉴于(build_<association>)在Rails中是一种非常奇怪且出乎意料的行为,如果您知道我的意思,那么寻找此答案的人数要多于实际问题的答案。
Max Williams

19

仔细查看错误消息。这是告诉你,你没有要求列user_id配置表。在模型中设置关系只是答案的一部分。

您还需要创建将user_id列添加到配置文件表的迁移。Rails希望它存在,否则,您将无法访问该配置文件。

有关更多信息,请查看以下链接:

协会基础


1
我刚发现我的问题。我正在学习的书没有很好地解释外键的创建。我创建了一个新迁移,该迁移为模型添加了外键。谢谢。
espinet

您是否需要每次自己创建列?我有这样的想法,它是自动发生的。我不知道我的主意是什么。
Rimian

您可以在使用命令行生成模型时添加列,例如rails g model profile user:references:index address:string bio:text
duykhoa

1

根据使用情况,可以方便地包装方法并在未找到时自动建立关联。

old_profile = instance_method(:profile)
define_method(:profile) do
  old_profile.bind(self).call || build_profile
end

现在调用该#profile方法将返回关联的配置文件或构建一个新实例。

来源: 猴子修补方法时,可以从新实现中调用重写的方法吗?


1
在当前的导轨上(在6.0.2.2上测试),您可以将其简化为:def profile; super || build_profile; end
格拉斯

-14

应该是一个has_one。如果build不起作用,则可以使用new

ModelName.new( :owner => @owner )

是相同的

@owner.model_names.build

11
这是不一样的:如果您使用build创建一个新的model_name,那么当保存@owner时,新的model_name也将被保存。因此,您可以使用build来创建将被保存在一起的父母和子女。如果您使用.new来创建模型名称,则情况并非如此-Max
Williams
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.