【问题标题】:Nested form with nested has_many, and has_one inside带有嵌套 has_many 和 has_one 的嵌套表单
【发布时间】:2014-10-31 20:19:16
【问题描述】:

我基本上遇到了与这篇文章相同的问题,尽管我的情况略有不同:has_many nested form with a has_one nested form within it

但正如该帖子中的其他人所提到的,提供的答案并不能解决问题。

建立关系使得 Invoice has_many items 并且每个 Item has_one 修饰符。我正在尝试制作一个 form_for Invoice,它允许使用创建许多项目,每个项目都有一个修饰符。

模型

class Invoice < ActiveRecord::Base
  has_many :items
  has_many :modifiers, through: :items

  accepts_nested_attributes_for :items
end

class Item < ActiveRecord::Base
  belongs_to :invoice
  belongs_to :modifier

  accepts_nested_attributes_for :modifier
end

class Modifier < ActiveRecord::Base
  has_one :item
end

控制器

class Invoice
  def new
    @invoice = Invoice.new
  end

  def edit
  end

  ...
end

视图(哈姆尔)

invoice.html.haml:
= form_for @invoice do |f|
  = f.text_field :status

  = f.fields_for :items do |builder|
    = render partial: "items/fields", locals: { :f => builder }
  = link_to_add_association 'New Item', f, :items, partial: "items/fields", id: "add-item-button"

items/_fields.html.haml:
.nested-fields
  - @item = @invoice.items.build
  = f.fields_for :modifier, @item.build_modifier do |modifier|
    = modifier.text_field :name

让我们回顾一下正在发生的事情。为了构建嵌套的 has_one 关系,我在嵌套字段部分中构建了一个项目,以便我可以构建 has_one 修饰符。这是因为 rails 要求您在 has_one 关系中显式调用“build_something”(通常这在控制器的 new 中调用,但我只想在有人单击“新建项目”按钮后进行构建)。对于创建新发票,此代码完美运行。检查控制台,我看到关系已创建,我可以验证修饰符是否已成功创建。

但是,当我回去编辑发票时,cocoon 知道我已经有一个修饰符,所以它调用部分一次来为我的单个修饰符创建必要的字段。这些字段为空。不过这是有道理的,因为 cocoon 正在渲染该部分,它正在构建一个带有新修饰符的新代码并将字段设置为空白。我可以确认这是正在发生的事情,因为一旦我正确保存了我的修改器,我就可以进入我的部分,删除两个构建调用,并查看正确显示保存的修改器信息的编辑页面。

当然,现在我已经删除了构建调用,表单不再保存我创建的任何修饰符。所以本质上,我需要那里的构建调用来构建新的修饰符,但如果我想查看它们,我就不能在其中拥有它们。

有没有人可以解决这种情况?我发现了多个堆栈溢出问题,但没有一个能解决这个问题。

【问题讨论】:

    标签: ruby-on-rails-4 has-many-through has-one nested-form-for cocoon-gem


    【解决方案1】:

    你说has_one,但在你的模型中我看到has_many

    您嵌套的部分items/_fields 是错误的:您构建了一个额外的项目,并且不需要这样做。 Coccon,在link_to_add_association 建立一个新的项目来插入。

    有两种方法可以做你想做的事。

    1) 在局部

    要在您的部分中正确处理它,您可以执行以下操作 (items/_fields.html.haml):

    .nested-fields
      - f.object.build_modifier if f.object.new_record?  
      = f.fields_for :modifier do |modifier|
        = modifier.text_field :name 
    

    在rails中,要引用表单的对象,可以使用f.object。请注意,这将起作用,但我们必须检查它是否是新创建的对象。或者,我们可以只检查modifier 是否存在。

    2) 使用:wrap_object 选项(documentation

    Cocoon 允许使用新创建的对象执行一些额外的代码。所以在你的情况下会变成:

    = link_to_add_association('New item', f, :items,
            :wrap_object => Proc.new { |item| item.build_modifier; item })
    

    【讨论】:

    • 选择了选项二,效果很好。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-28
    • 2018-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多