簡體   English   中英

Rails 2級嵌套forms

[英]Rails 2 level nested forms

我稍微修改並擴展了構建嵌套 forms 的示例以實現第二級嵌套。 一切都完美地顯示在表格上。 此人的數據在兩個嵌套級別都正確顯示。 相應的 JS 腳本用於添加和刪除嵌套的 forms。 所有 3 個都是使用腳手架生成的。 形式

但是當我點擊更新時,只有主窗體和第一個嵌套級別(地址)被更新。 第二個嵌套級別(嵌套地址)不會更新。 雖然我也從 controller 的第二個嵌套級別獲取參數( “name”=>“UPDATE NAME OF NESTED ADDRESS” )。

{
"_method"=>"patch", 
"authenticity_token"=>"VZ09CR-aO2D4Wv3AwEa5PHXo-mA_--c6QPUN6f0Gb_9SJJSL2gIwzCl4G4SbzRy2t3wxJHytBWiPwysNJMrWgg", 
"person"=>{
  "first_name"=>"Liz", 
  "last_name"=>"Smith", 
  "addresses_attributes"=>{
    "0"=>{
      "_destroy"=>"false", 
      "kind"=>"Some kind", 
      "street"=>"Some street", 
      "nested_addresses_attributes"=>{
        "0"=>{
          "_destroy"=>"false", 
          "name"=>"UPDATE NAME OF NESTED ADDRESS", 
          "id"=>"1"
        }
      }, 
  "id"=>"10"}}}, 
"commit"=>"Update Person", 
"controller"=>"people",
"action"=>"update", 
"id"=>"3"}

我知道即使是第一個嵌套級別也在幕后神奇地處理,但我不明白如何? 以及如何處理第二級? 通常,創建更新、刪除方法不適用於第二個嵌套級別。

楷模


class Person < ApplicationRecord
  has_many :addresses, inverse_of: :person, :dependent => :destroy
  has_many :nested_addresses, through: :addresses, inverse_of: :person, :dependent => :destroy
  accepts_nested_attributes_for :addresses, allow_destroy: true, reject_if: :all_blank
  accepts_nested_attributes_for :nested_addresses, allow_destroy: true, reject_if: :all_blank
  validates :first_name, presence: true
  validates :last_name, presence: true
end
class NestedAddress < ApplicationRecord
  belongs_to :address
  validates :name, presence: true
end
class Address < ApplicationRecord
  belongs_to :person, optional: true
  has_many :nested_addresses, inverse_of: :address, :dependent => :destroy
  accepts_nested_attributes_for :nested_addresses, allow_destroy: true, reject_if: :all_blank
  validates :kind, presence: true
  validates :street, presence: true
end

控制器

def person_params
  params.require(:person).permit(:first_name, :last_name, addresses_attributes: [:id, :kind, :street, :_destroy], nested_addresses_attributes: [:id, :name, :_destroy])
end
def address_params
  params.require(:address).permit(:kind, :street, :person_id, nested_addresses_attributes: [:id, :name, :_destroy])
end
def nested_address_params
  params.require(:nested_address).permit(:name, :address_id)
end

人/_form.html.erb

<%= form_with model: @person, local: true do |f| %>
  <%= render "shared/validation-messages", object: @person %>
  <%= f.label :first_name %>
  <%= f.text_field :first_name, class: 'form-control' %>
  <%= f.label :last_name %>
  <%= f.text_field :last_name, class: 'form-control' %>

  <br>
  <fieldset>
    <legend>Addresses:</legend>
    <%= f.fields_for :addresses do |addresses_form| %>
      <%= render "address_fields", f: addresses_form %>
    <% end %>
    <br>
    <%= link_to_add_fields "Add Addresses", f, :addresses, 'btn btn-outline-secondary'%>
  </fieldset>
  <br>
  <%= f.submit class: 'btn btn-success' %>
  <% if params[:action] === "edit" && params[:controller] === "people" %>
    <%= link_to "Delete Person", person_path(@person), method: :delete, data: { confirm: "Are You Sure?" }, class: 'btn btn-outline-danger' %>
  <% end %>
<% end %>

人/_address_fields.html.erb

<div class="card nested-fields">
  <div class="card-header">
    <div><%= f.object.id %></div>
  </div>
  <div class="card-body">
    <%= f.hidden_field :_destroy %>
    <div>
      <%= f.label :kind %>
      <%= f.text_field :kind, class: 'form-control' %>
    </div>
    <div>
      <%= f.label :street %>
      <%= f.text_field :street, class: 'form-control' %>
    </div>
    <br>
    <fieldset>
      <legend>Nested addresses:</legend>
      <%= f.fields_for :nested_addresses do |nested_addresses_form| %>
        <%= render "nested_address_fields", f: nested_addresses_form %>
      <% end %>
      <br>
      <%= link_to_add_fields "Add Nested Addresses", f, :nested_addresses, 'btn btn-outline-secondary btn-sm' %>
    </fieldset>
    <br>
    <div>
      <%= link_to "Remove address", '#', class: "remove_fields btn btn-outline-danger btn-sm" %>
    </div>
  </div>
</div>

人/_nested_address_fields.html.erb

<div class="card nested-fields">
  <div class="card-body">
    <%= f.hidden_field :_destroy %>
    <div>
      <%= f.label :name %>
      <%= f.text_field :name %>
    </div>
    <br>
    <div>
      <%= link_to "Remove nested address", '#', class: "remove_fields btn btn-outline-danger btn-sm" %>
    </div>
  </div>
  <br>
</div>

助手/application_helper.rb

def link_to_add_fields(name, f, association, cl)
    new_object = f.object.send(association).klass.new
    id = new_object.object_id
    fields = f.fields_for(association, new_object, child_index: id) do |builder|
      render(association.to_s.singularize + "_fields", f: builder)
    end
    link_to(name, '#', class: 'add_fields ' + cl, data: {id: id, fields: fields.gsub("\n", "")}, role: 'button')
  end

您的強參數permit調用應反映參數的實際嵌套結構:

def person_params
  params.require(:person).permit(
    :first_name, :last_name,
    addresses_attributes: [
      :id, :kind, :street, :_destroy,
      { nested_addresses_attributes: [:id, :name, :_destroy] } # <= note the hash
    ]
  )
end

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM