[英]In Rails 5.1, how do I use one form to update two tables?
I have been trying to get one form to update two tables in Ruby on Rails. 我一直在尝试获取一种形式来更新Ruby on Rails中的两个表。 I have done a fairly exhaustive search on here and I'm finding the guides a little confusing.
我在这里进行了相当详尽的搜索,发现这些指南有些令人困惑。 The closest answer I have found is this:
我找到的最接近的答案是这样的:
Ruby on Rails Saving in two tables from one form Ruby on Rails从一种形式保存在两个表中
I have mostly copied this answer but I still can't get it to work. 我大部分都复制了此答案,但仍然无法正常工作。 Here are the relevant bits of code:
以下是相关的代码位:
Models - I have two models, supplier and account. 模型-我有两个模型,供应商和帐户。 Each supplier should have one account.
每个供应商应有一个帐户。
class Supplier < ApplicationRecord
has_one :account
accepts_nested_attributes_for :account
end
class Account < ApplicationRecord
belongs_to :supplier
end
Form - not sure if this is entirely correct 表格-不确定这是否完全正确
<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 %>
And finally, the SuppliersController
最后是
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
I am getting an undefined method error on the second line of the new action of the SuppliersController
and I don't know why. 我在
SuppliersController
的新操作的第二行上收到未定义的方法错误,我不知道为什么。
Debugging printout for create action in SupplierController
: 在
SupplierController
调试打印输出以创建操作:
Started POST "/suppliers" for 127.0.0.1 at 2017-11-03 08:25:25 -0600 Processing by SuppliersController#create as HTML Parameters: {"utf8"=>"✓", "authenticity_token"=>"KEqvPgjrYmuBux3qWCQJLAkSLQ4z1ns4HsK2P9sWlhVegpjhik/JoWT3vlL/kP42XpU8adllOaqSA16izYJ0SA==", "supplier"=>{"name"=>"", "account_attributes"=>{"account_number"=>""}}, "commit"=>"Create Supplier"} 在2017年11月3日08:25:25 -0600开始为127.0.0.1的POST“ /供应商”供应商Controller#create作为HTML参数进行处理:{“ utf8” =>“✓”,“ authenticity_token” =>“ KEqvPgjrYmuBux3qWCQJLAkSLQ4z1ns4HsK2P9sWl JoWT3vlL / kP42XpU8adllOaqSA16izYJ0SA ==“,”供应商“ => {”名称“ =>”“,” account_attributes“ => {” account_number“ =>”“}},” commit“ =>”创建供应商“}
(0.1ms) begin transaction (0.1ms)开始交易
SQL (0.5ms) INSERT INTO "suppliers" ("created_at", "updated_at", "name") VALUES (?, ?, ?) [["created_at", "2017-11-03 14:25:25.388933"], ["updated_at", "2017-11-03 14:25:25.388933"], ["name", "Bob"]] SQL(0.5ms)插入“供应商”(“ created_at”,“ updated_at”,“名称”)值(?,?,?)[[“ created_at”,“ 2017-11-03 14:25:25.388933”] ,[“ updated_at”,“ 2017-11-03 14:25:25.388933”],[“名称”,“鲍勃”]]
(0.6ms) commit transaction (0.0ms) begin transaction (0.6ms)提交事务(0.0ms)开始事务
Supplier Load (1.0ms) SELECT "suppliers".* FROM "suppliers" WHERE "suppliers"."id" = ? 供应商负载(1.0毫秒)选择“供应商”。*从“供应商”中选择“供应商”。“ id” =? LIMIT ?
LIMIT? [["id", 6], ["LIMIT", 1]] SQL (0.3ms) INSERT INTO "accounts" ("created_at", "updated_at", "account_number", "supplier_id") VALUES (?, ?, ?, ?) [["created_at", "2017-11-03 14:25:25.424367"], ["updated_at", "2017-11-03 14:25:25.424367"], ["account_number", "456456456"], ["supplier_id", 6]]
[[“ id”,6],[“ LIMIT”,1]] SQL(0.3ms)插入“帐户”(“ created_at”,“ updated_at”,“帐户编号”,“供应商id”)值(?,?, ?,?)[[“ created_at”,“ 2017-11-03 14:25:25.424367”],[“ updated_at”,“ 2017-11-03 14:25:25.424367”],[“ account_number”,“ 456456456 “],[” supplier_id“,6]]
(0.6ms) commit transaction (0.6ms)提交事务
Supplier: #Supplier id: 6, created_at: "2017-11-03 14:25:25", updated_at: "2017-11-03 14:25:25", name: "Bob" 供应商:#Supplier id:6,created_at:“ 2017-11-03 14:25:25”,updated_at:“ 2017-11-03 14:25:25”,名称:“ Bob”
Account: #Account id: 1, created_at: "2017-11-03 14:25:25", updated_at: "2017-11-03 14:25:25", account_number: "456456456", supplier_id: 6 帐户:#帐户ID:1,created_at:“ 2017-11-03 14:25:25”,updated_at:“ 2017-11-03 14:25:25”,account_number:“ 456456456”,Supplier_id:6
(0.0ms) begin transaction (0.0ms) commit transaction (0.0ms)开始事务(0.0ms)提交事务
Redirected to http://localhost:3000/suppliers Completed 302 Found in 51ms (ActiveRecord: 4.6ms) 重定向到http:// localhost:3000 / suppliers已完成302在51ms内找到(ActiveRecord:4.6ms)
Your issue is that build_account
is a method on a supplier object. 您的问题是
build_account
是供应商对象上的方法。 As you have your code, it is currently trying to run build_account as if it was a method on the SuppliersController 有了代码后,它当前正在尝试运行build_account,就像它是SuppliersController上的方法一样
So, you should try updating your controller method for new to: 因此,您应该尝试将控制器方法更新为new:
def new
@supplier = Supplier.new
@account = @supplier.build_account
end
This calls the build_account
against the supplier object you have just instantiated, returning the result as an instantiated account object, associated with the supplier instance it belongs to. 这将针对您刚刚实例化的供应商对象调用
build_account
,并将结果作为实例化的帐户对象返回,并与其所属的供应商实例相关联。
The build_account method is generated through the association you have defined in your supplier model, where you say has_one :account
. build_account方法是通过您在供应商模型中定义的关联(您说
has_one :account
。 The docs here http://guides.rubyonrails.org/association_basics.html#has-one-association-reference describe all the methods that are created in this way. http://guides.rubyonrails.org/association_basics.html#has-one-association-reference此处的文档介绍了以这种方式创建的所有方法。
EDIT 编辑
Following up on the question about the create action, the controller should be updated. 在跟上有关创建动作的问题之后,应该更新控制器。 In the comments we have debugged the models and they appear to work as we would hope, so once updated the controller should work as:
在注释中,我们已经调试了模型,它们似乎可以按我们希望的那样工作,因此一旦更新,控制器应以下列方式工作:
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
Based on the association autosave functionality, new associated records (account) should be automatically created based on the nested parameters being passed from the form, at the point the supplier is saved, without having to add any additional code to explicitly handle this. 基于关联自动保存功能,应在保存供应商时基于从表单传递的嵌套参数自动创建新的关联记录(帐户),而不必添加任何其他代码来显式处理此问题。 More autosave options are documented here: http://api.rubyonrails.org/classes/ActiveRecord/AutosaveAssociation.html
更多自动保存选项记录在这里: http : //api.rubyonrails.org/classes/ActiveRecord/AutosaveAssociation.html
from the guides, this section 从本节的指南
4.1.1 Methods Added by belongs_to 4.1.1归属者添加的方法
each instance of the Book model will have these methods: Book模型的每个实例将具有以下方法:
So as my friend points below, I assume 因此,正如我的朋友在下面指出的那样
@supplier = Supplier.build_account // wrong
@account = @supplier.build_account
would be correct 会是正确的
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.