Rails 2 级嵌套表单 模型控制器people/_form.html.erbpeople/_address_fields.html.erbpeople/_nested_address_fields.html.erbhelpers/application_helper.rb

问题描述

我稍微修改并扩展了构建嵌套表单的示例,以实现第二级嵌套。一切都完美地显示在表格上。人的数据正确显示在两个嵌套级别。相应的 JS 脚本用于添加和删除嵌套表单。所有 3 个都是使用支架生成的。

Form

但是当我点击更新时,只有主窗体和第一个嵌套级别(地址)被更新。第二级嵌套(嵌套地址)不会更新。虽然我也从控制器中的第二个嵌套级别获取参数("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,:dependent => :destroy
  accepts_nested_attributes_for :addresses,allow_destroy: true,reject_if: :all_blank
  accepts_nested_attributes_for :nested_addresses,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,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,:person_id,:_destroy])
end
def nested_address_params
  params.require(:nested_address).permit(:name,:address_id)
end

people/_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 %>

people/_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",: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>

people/_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>

helpers/application_helper.rb

def link_to_add_fields(name,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

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)