表单提交时未添加嵌套字段

Nested fields not being added on form submit

我正在使用 cocoon gem 来尝试添加一个属于另一个具有嵌套字段的对象。我有一个 'user_resolution',其中有很多 'milestones'。我已经在这两个模型中相应地建立了关联。出于某种原因,里程碑无法创建,但是如果我在数据库中手动添加一个里程碑,我可以成功更新它。我可以动态添加字段并使用 cocoon gem 删除它们,但仅此而已。当我单击 'add milestone' 时,它会将我重定向到用户解决方案的显示视图,并抛出一条成功消息,说明用户解决方案已更新,没有抛出任何错误,但里程碑 is/are 未创建。

user_resolution.rb

has_many :milestones
accepts_nested_attributes_for :milestones, reject_if: :all_blank, allow_destroy: true

milestone.rb

belongs_to :user_resolution

我已经在编辑视图中设置了嵌套表单,目前我只希望用户在编辑视图中为解决方案添加一个里程碑。

user_resolutions/edit.html.erb

<%= form_for(@user_resolution) do |f| %>

  <div class="field">
    <%= f.label :name %><br>
    <%= f.text_field :name %>
  </div>
  <div class="field">
    <%= f.label :description %><br>
    <%= f.text_area :description %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>

    <%= f.fields_for :milestones do |milestone| %>
      <%= render 'milestone_fields', f: milestone %>
    <% end %>

    <%= link_to_add_association 'Add Milestone', f, :milestones %>
    <%= f.submit "Add Milestone" %>

<% end %>

_milestone_fields.html.erb

<div class="nested-fields">
   <div class="field-row">
       <%= f.label :name, 'Name' %>
       <%= f.text_field :name %>
   </div>
   <div class="field-row">
       <%= f.label :description, 'Name' %>
       <%= f.text_area :description %>
   </div>
   <div class="field-row">
       <%= f.label :severity, 'severity' %>
       <%= f.check_box :severity %>
   </div>
   <div class="field-row">
       <%= f.label :target_date, 'target_date' %>
       <%= f.date_select :target_date %>
   </div>

   <%= link_to_remove_association 'Remove', f %>

</div>

用户分辨率控制器中允许的参数还包含以下内容

milestones_attributes: [:id, :user_resolution_id, :name, :description, :target_date, :severity, :complete, :_destroy]

里程碑本身没有视图,它们只有一个模型和一个控制器。控制器创建操作(我不确定嵌套表单是否需要)包含以下标准代码

def create
    @milestone = Milestone.new(milestone_params)

    if @milestone.save
        redirect_to user_resolutions_path, 
        :flash => { :success => "You successfully created a milestone" }
    else
        redirect_to new_milestone_path, 
        :flash => { :error => "Oops something went wrong. Try again." }
    end
end

我已尽我所能提供信息,但如果您需要任何其他信息,请告诉我。谢谢大家。

which i'm unsure is required for nested forms

您不需要 milestonescreate 操作 - 它们将从 user_resolutions#create 控制器操作中填充。

这有几件事要看。我会在这里详细介绍一些。这不会是一个具体的答案,但可能会帮助您指明正确的方向。


首先,您需要确保收到正确的参数

Cocoon 在构建嵌套表单方面做得很好 - 您需要确保它符合 Rails' 嵌套属性结构。

为此,您应该 right-click > view source

f.fields_for 部分(在 HTML 中不会这样称呼),您将查找与以下内容等效的内容:

<input type="text" name="milestones_attributes[0][name]" value="">

需要注意的重要一点是 name...

每次您使用表单,或 any Rails view helper 时,您 真的 只是建筑标准 HTML。 form_for 只是创建了一个 HTML 表单,因此其中包含的任何参数都需要遵守特定结构,以便 Rails 识别参数。

f.fields_for 元素通常被称为 x_attributes[:id][:param] - 这被传递给 Rails,循环遍历每个 [:id] 以确定要添加的嵌套参数的数量.

以上命名结构需要查一下出处。如果你看到它,那很好。如果没有,则说明您没有正确构建表单。


其次,您需要确保您的对象在控制器中构建

我不确定 Cocoon 是如何做到这一点的,但基本上,每次使用 f.fields_for 时,您都必须先构建关联对象:

def new
    @user_reservation = UserReservation.new
    @user_reservation.milestones.build #-> this is what makes f.fields_for work
end

如果第一步显示的元素命名不正确,则表示您的关联对象未构建(这就是它们未被识别的原因)。

要测试它,您应该在 new 方法中构建关联对象,然后再发送。


最后,您需要 post 您的参数

这些详细地告诉您 Rails 对嵌套属性做了什么,允许您确定它们发生了什么。

抱歉冗长的回答。无论如何你都不会收到任何答案,所以我觉得给你一些东西是明智的。