如何在具有多向关联的Rails中创建三层嵌套对象

问题描述 投票:0回答:1

名为Triple nested Forms in Rails的文章对创建用于保存三个嵌套对象的表单进行了很好的描述。给出的示例是创建一个Showhas_many Seasons,并且每个Season具有多个Episodes。另外,Episode --> belongs_to --> Season --> belongs_to --> Show。节目是这样创建的:

def new
@show = Show.new
@show.seasons.build.episodes.build
end

表格看起来像这样:

<%= form.fields_for :seasons do |s| %>
    <%= s.label :number %>
    <%= s.number_field :number %>    <%= s.fields_for :episodes do |e| %>
      <%= e.label :title %>
      <%= e.text_field :title %>
    <% end %> 
 <% end %>
<% end %>

这似乎很简单,因为所有关联都在一个方向上运行。我正在尝试做类似但更复杂的事情。我有一个Parent模型,其中每个Parent具有多个Children,并且每个Child都注册了一个School。在指定ChildrenChild的复数之后,关联将必须像这样:

Parent has_many Children, accepts_nested_attributes_for :children
Child belongs_to Parent, belongs_to School, accepts_nested_attributes_for :school
School has_many Children, accepts_nested_attributes_for :children

图形上看起来像这样:

Parent <-- belongs_to <-- Child --> belongs_to --> School

每个父级也与一个用户相关联,例如:

User has_many :parents

[父母,子女和学校的数据以以下形式输入(使用Simple Form gem生成),其中,作为从学校表中填充的下拉选择器输入学校:

@schools = School.all

<%= simple_form_for (@parent) do |f| %>
     <%= f.input :name, label: 'name' %>
     <%= f.simple_fields_for :children, @children do |child_form| %>
         <%= child_form.input :name, label: "Child Name" %>
         <%= child_form.simple_fields_for :school, @school do |school %>
             <%= school.collection_select :id, @schools, :id, :name, {}, {} %>
            <% end %>
     <% end %>
<% end %>

我设置了new控制器方法,以创建一个在现有Parent中注册了三个ChildrenSchool。然后我尝试将ChildrenSchool表中已经存在且ID = 1的schools关联。

def new
   @parent = Parent.new
   # creating 3 children
   @children = Array.new(3) {@parent.children.build}
   @school = School.find(1)
   @school.children.build
end

这将引发错误。

Couldn't find School with ID=1 for Child with ID=

错误位于create方法的第一行,如下所示:

def create
    @parent = Parent.new(parent_params.merge(:user => current_user))
    if @parent.save
        redirect_to root_path
    else
        render :new, :status => :unprocessable_entity
    end
end

def parent_params
    params.require(:parent).permit(:name, :child_attributes => [:id, :name, age, :school_attributes => [:id, :name]])
end

由于错误文本状态为"Child with ID= ",因此必须在分配新Children的ID之前引发错误。当School表中存在ID = 1的schools时,为什么找不到它?或者,这是否意味着在尝试保存School实例之前,Child记录未与该实例正确关联?如果是这样,我该如何解决该关联?

ruby-on-rails ruby nested simple-form nested-forms
1个回答
0
投票

具有嵌套属性的最常见的误解/错误之一是认为您需要它来进行简单的关联分配。你不知道您只需要传递一个ID或ID数组即可。

如果用户同时创建一所学校,则只需要接受学校的嵌套属性。在那种情况下,使用Ajax而不是将所有内容塞入一个大型动作中可能是一个更好的主意。

<%= simple_form_for (@parent) do |f| %>
  <%= f.input :name, label: 'name' %>
  <%= f.simple_fields_for :children, @children do |child_form| %>
    <%= child_form.input :name, label: "Child Name" %>
    <%= child_form.associaton :school, 
        collection: @schools, label_method: :name %>
  <% end %>
<% end %>
def parent_params
  params.require(:parent).permit( :name, 
    child_attributes: [:id, :name, :age, :school_id]]
  )
end
© www.soinside.com 2019 - 2024. All rights reserved.