使用 Cocoon 在 link_to_add_association 单击时自动添加嵌套子部分

Automatically adding nested child partials on link_to_add_association click using Cocoon

我有一个包含 4 个嵌套级别的表单,我用它来动态添加项目、发货和计算成本。我已将表单设置为 add/remove 我需要的一切,只需单击按钮即可。关于页面初始呈现的一切都符合预期。

但是,当我添加新的中级嵌套实例(SubQuote 和 QuoteShipment)时,它只呈现自身(例如 SubQuote),而不呈现其部分 (QuoteShipment) 中引用的任何部分。我想要单击按钮以自动呈现其下方的所有嵌套部分。

我的相关模型结构化:

class Quote < ApplicationRecord
  has_many :sub_quotes, dependent: :destroy, inverse_of: :quote
  accepts_nested_attributes_for :sub_quotes, reject_if: :all_blank
end


class SubQuote < ApplicationRecord
    belongs_to :quote
    has_many :quote_shipments, dependent: :destroy, inverse_of: :sub_quote
    accepts_nested_attributes_for :quote_shipments, reject_if: :all_blank
end

class QuoteShipment < ApplicationRecord
    has_many :quote_items, dependent: :destroy, inverse_of: :quote_shipment, class_name: "::QuoteItem"
    belongs_to :sub_quote
    accepts_nested_attributes_for :quote_items, reject_if: :all_blank
end

Class QuoteItem < ApplicationRecord
    belongs_to :quote_shipment
end

部分用于 SubQuote class,它在页面加载时呈现 QuoteShipment 部分,但在 link_to_add_association 单击时不呈现。

<div class="col nested-sub_quote-fields" id="sub_quote_identifier">

  <div class="row">
    <%= link_to_remove_association button_tag('remove sub_quote', type: "button", class: "btn btn-sm btn-outline red-btn add-quote"), f , { wrapper_class: "nested-sub_quote-fields" }%>
  </div>

  <div class="row" class="">
  
    <div id="sub_quote" class="col mt-0 mt-md-4 mb-4 p-0">
      <div class="col ">
        <div class="col-lg col-sm-12 col-md-12">
          <%= f.fields_for :quote_shipments do |shipment| %>
            <%= render partial: "quotes/quote_shipment_fields", :locals => { :f => shipment } %>
          <% end %>
          <div class='links'>
            <%= link_to_add_association button_tag('Add Shipment', type: "button", class: "btn btn-sm btn-outline btn-primary add-quote"), f, :quote_shipments %>
          </div>
        </div>
      </div>
    </div>
    
    <div class="col-lg-5 col-sm-12 col-md-12">
      <%= render partial: "quotes/cost", locals: { f: f } %>
    </div>
    
  </div>
</div>

例如上面的关系:

我试过:

我认为在更糟糕的情况下,我可以为每个不同级别的 link_to_add_association 按钮生成不同的部分,但这似乎非常多余

link_to_add_association:wrap_object 选项(选中 documentation),允许在渲染部分之前添加额外的初始化。

所以在你的情况下你可以这样:

= link_to_add_association button_tag('Add Shipment', type: "button", class: "btn btn-sm btn-outline btn-primary add-quote"), 
                          f, :quote_shipments, 
                          wrap_object: Proc.new{|shipment| shipment.quote_items.build; shipment }

wrap_object 局部你可以做任何你想要的初始化,只要你 return 要渲染的嵌套项目(在这个例子中 shipment)。 在这个例子中我们 build a QuoteItem 所以它会被渲染。

对于 SubQuote 你可以做类似的事情。例如。像

wrap_object: Proc.new{|sub_quote| shipment = sub_quote.quote_shipments.build; shipment.quote_items.build; sub_quote }