我一直试图让一个表单更新Ruby on Rails中的两个表。我在这里做了相当详尽的搜索,我发现指南有点令人困惑。我找到的最接近的答案是:
Ruby on Rails Saving in two tables from one form
我大部分都复制了这个答案,但我还是无法让它发挥作用。以下是相关的代码:
模型 - 我有两个模型,供应商和帐户。每个供应商应该有一个帐户。
class Supplier < ApplicationRecord
has_one :account
accepts_nested_attributes_for :account
end
class Account < ApplicationRecord
belongs_to :supplier
end
表格 - 不确定这是否完全正确
<h2>Please enter a supplier</h2>
<%= form_for(@supplier) do |form| %>
<p>
<%= form.label :name %><br>
<%= form.text_field :name %>
</p>
<p>
<%= form.fields_for :account do |f| %>
<%= f.label :account_number %><br>
<%= f.text_field :account_number %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>
<% end %>
最后,SuppliersController
class SuppliersController < ApplicationController
def index
@suppliers = Supplier.all
end
def new
@supplier = Supplier.new
@supplier = build_account
end
def create
@supplier = suppliers.build(supplier_params)
if @supplier.save
redirect_to suppliers_path
else
redirect_to root_path
end
end
private
def supplier_params
params.require(:supplier).permit(:name, account_attributes:
[:account_number])
end
end
我在SuppliersController
的新操作的第二行收到未定义的方法错误,我不知道原因。
调试SupplierController
中的创建操作的打印输出:
开始POST&#34; /供应商&#34;对于127.0.0.1在2017-11-03 08:25:25 - 0600 由SuppliersController处理#create as HTML 参数:{&#34; utf8&#34; =&gt;&#34;✓&#34;,&#34; authenticity_token&#34; =&gt;&#34; KEqvPgjrYmuBux3qWCQJLAkSLQ4z1ns4HsK2P9sWlhVegpjhik / JoWT3vlL / kP42XpU8adllOaqSA16izYJ0SA ==&#34; ,&#34;供应商&#34; =&gt; {&#34;名称&#34; =&gt;&#34;&#34;,&#34; account_attributes&#34; =&gt; {&#34; account_number& #34; =&gt;&#34;&#34;}},&#34;提交&#34; =&gt;&#34;创建供应商&#34;}
(0.1ms)开始交易
SQL(0.5ms)INSERT INTO&#34;供应商&#34; (&#34; created_at&#34;,&#34; updated_at&#34;,&#34; name&#34;)VALUES(?,?,?)[[&#34; created_at&#34;,&#34 ; 2017-11-03 14:25:25.388933"],[&#34; updated_at&#34;,&#34; 2017-11-03 14:25:25.388933&#34;],[&# 34;姓名&#34;,&#34; Bob&#34;]]
(0.6ms)提交事务 (0.0ms)开始交易
供应商负荷(1.0ms)SELECT&#34;供应商&#34;。* FROM&#34;供应商&#34;在哪里&#34;供应商&#34;。&#34; id&#34; =?限制? [[&#34; id&#34;,6],[&#34; LIMIT&#34;,1]] SQL(0.3ms)INSERT INTO&#34; accounts&#34; (&#34; created_at&#34;,&#34; updated_at&#34;,&#34; account_number&#34;,&#34; supplier_id&#34;)VALUES(?,?,?,?)[[& #34; created_at&#34;,&#34; 2017-11-03 14:25:25.424367"],[&#34; updated_at&#34;,&#34; 2017-11-03 14:25 :25.424367&#34;],[&#34; account_number&#34;,&#34; 456456456&#34;],[&#34; supplier_id&#34;,6]]
(0.6ms)提交事务
供应商:#Supplier id:6,created_at:&#34; 2017-11-03 14:25:25&#34;,updated_at:&#34; 2017-11-03 14:25:25&#34; ,姓名:&#34; Bob&#34;
帐户:#Account id:1,created_at:&#34; 2017-11-03 14:25:25&#34;,updated_at:&#34; 2017-11-03 14:25:25&#34; ,account_number:&#34; 456456456&#34;,supplier_id:6
(0.0ms)开始交易 (0.0ms)提交事务
重定向到http://localhost:3000/suppliers 完成302发现在51ms(ActiveRecord:4.6ms)
答案 0 :(得分:0)
您的问题是build_account
是供应商对象上的方法。当你有你的代码时,它正在尝试运行build_account,就像它是SuppliersController上的方法一样
因此,您应该尝试将您的控制器方法更新为:
def new
@supplier = Supplier.new
@account = @supplier.build_account
end
这会针对您刚刚实例化的供应商对象调用build_account
,将结果作为实例化的帐户对象返回,与其所属的供应商实例相关联。
build_account方法是通过您在供应商模型中定义的关联生成的,您在其中说has_one :account
。这里的文档http://guides.rubyonrails.org/association_basics.html#has-one-association-reference描述了以这种方式创建的所有方法。
修改强>
关于创建操作的问题,应该更新控制器。在评论中我们调试了模型,它们看起来像我们希望的那样工作,所以一旦更新,控制器应该工作:
def create
# Created a Supplier, but not yet persisted.
@supplier = Supplier.new(supplier_params)
# Persists the supplier, giving him an id, which can then be used
# through implicit autosave functionality to take the nested params
# to build the associated account. All of these operations are wrapped
# in a single DB transaction, ensuring nothing is left dangling if
# there is a validation failure
if @supplier.save
redirect_to suppliers_path
else
redirect_to root_path
end
end
基于关联自动保存功能,应根据从表单传递的嵌套参数,在保存供应商时自动创建新的关联记录(帐户),而无需添加任何其他代码来显式处理此。此处记录了更多自动保存选项:http://api.rubyonrails.org/classes/ActiveRecord/AutosaveAssociation.html
答案 1 :(得分:-1)
来自指南,本节
4.1.1 Methods Added by belongs_to
Book模型的每个实例都将包含以下方法:
正如我的朋友指出的那样,我假设
@supplier = Supplier.build_account // wrong
@account = @supplier.build_account
是正确的