当前位置: 首页 > 知识库问答 >
问题:

在 Rails 5.1 中,如何使用一个表单来更新两个表?

祁聪
2023-03-14

我一直在尝试获得一种表单来更新Ruby on Rails中的两个表。我在这里进行了相当详尽的搜索,我发现指南有点令人困惑。我找到的最接近的答案是:

Ruby on Rails 从一个窗体保存在两个表中

我大部分时间都复制了这个答案,但我仍然无法让它工作。以下是相关的代码位:

模型-我有两个模型,供应商和客户。每个供应商应有一个账户。

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 %>

最后是< code >供应商控制器

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的新操作的第二行得到一个未定义的方法错误,我不知道为什么。

调试打印输出以在供应商控制器中创建操作:

在 2017-11-03 08:25:25 -0600 开始为 127.0.0.1 发布 “/suppliers” 由供应商控制器#创建为 HTML 参数: {“utf8”=

(0.1ms)开始事务

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]、[名称、Bob]

(0.6ms)提交事务(0.0ms)开始事务

供应商负载(1.0 毫秒) 选择“供应商”。 从“供应商”到“供应商”。id“ = ?限制?[[“id”, 6], [“限制”, 1]]SQL (0.3ms) 插入到“帐户”(“created_at”、“updated_at”、“account_number”、“supplier_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)提交事务

供应商:#供应商id: 6,created_at:"2017-11-03 14:25:25",updated_at:"2017-11-03 14:25:25",姓名:"Bob"

账户:#账户id: 1,已创建_at: "2017-11-03 14:25:25 ",已更新_at: "2017-11-03 14:25:25 ",账户_编号:" 456456456 ",供应商_id: 6

(0.0毫秒)开始事务(0.0毫秒)提交事务

已重定向至“http://localhost:3000/供应商在51毫秒内完成302个(活动记录:4.6毫秒)”诊断树

共有2个答案

习洲
2023-03-14

从指南来看,本节

4.1.1由belongs_to添加的方法

图书模型的每个实例都有这些方法:

因此,正如我的朋友在下面指出的,我认为

@supplier = Supplier.build_account // wrong
@account = @supplier.build_account 

是正确的

商正诚
2023-03-14

您的问题是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

 类似资料:
  • 问题内容: 我正在尝试使用表B中的数据更新表A。我认为我可以执行以下操作: 但是a,这行不通。 有人知道我该怎么做吗? 问题答案: 您的查询不起作用,因为您没有 FROM 子句来指定要通过A / B别名的表。 请尝试使用以下内容: 就我个人而言,我更喜欢使用更明确的联接语法以保持清晰,即

  • 我有两份清单: 我想要一个新的名单,比如: 我尝试了以下方法: 但有一些严重的错误

  • 问题内容: 我有两个表需要相同的值以实现非规范化。 这是查询。 第一张桌子 第二张桌子 如您所见,两个表之间的唯一区别是它们的名称和两个表没有该字段 无论如何将两个更新合并为一个? 问题答案: 如文档中所述,应该可以进行多表更新。 http://dev.mysql.com/doc/refman/5.5/en/update.html 注意:多表不支持LIMIT,因此根据具体情况,这可能会引起更多麻烦

  • 问题内容: 我看到这对笨论坛 考虑以下代码 这显然是您在Codeigniter中这样做的方式 实际上这是行不通的。我看了一下生成的SQL,结果甚至没有提到联接。 有谁知道如何使用Codeigniter的Active Record数据库类对联接进行更新? 问题答案: 我发现的一种解决方案是完全删除联接并将联接条件移到“ where”函数中,此外,您还需要更改更新字符串以包括新表。

  • 我有一张像下面这样的桌子, ID姓名电子邮件性别 这个表中已经有了一些值。 现在,我用下面的查询来添加年龄。 alter table tblPerson add Age int 现在,我的行结构看起来像 ID姓名电子邮件性别年龄 现在,我有了年龄表。有任何查询可以将这些年龄添加到新创建的列中吗? 所有年龄都是根据ID排序的。因此,如果需要逻辑,则不需要。我只需要添加列数据。 谢谢

  • 我正在设计一个使用html和php的登录页面。它包括两个按钮,一个用于登录,另一个用于重定向到注册页面。我计划使用php代码验证同一页面上的登录数据。这是我的密码 但是注册按钮工作不正常。它不会重定向到注册页面。我不想把登记按钮放在表格外面。我希望保持相同的设计并实现所需的功能。