我正在使用 cocoon gem 来尝试添加一个属于另一个具有嵌套字段的对象。我有一个包含许多“里程碑”的“user_resolution”。我已经在这两个模型中相应地建立了关联。出于某种原因,里程碑无法创建,但是如果我在数据库中手动添加一个里程碑,我可以成功更新它。我可以动态添加字段并使用 cocoon gem 删除它们,仅此而已。当我单击“添加里程碑”时,它会将我重定向到用户解决方案的显示 View 并抛出成功消息,说明用户解决方案已更新,不会抛出任何错误,但不会创建里程碑。
user_resolution.rb
has_many :milestones
accepts_nested_attributes_for :milestones, reject_if: :all_blank, allow_destroy: true
里程碑.rb
belongs_to :user_resolution
我已经在编辑 View 中设置了嵌套表单,因为现在我只希望用户在编辑 View 中为解决方案添加一个里程碑。
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>
用户分辨率 Controller 中允许的参数还包含以下内容
milestones_attributes: [:id, :user_resolution_id, :name, :description, :target_date, :severity, :complete, :_destroy]
里程碑本身没有 View ,它们只有一个模型和一个 Controller 。 Controller 创建操作(我不确定嵌套表单是否需要)包含标准的以下代码
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
你不需要 create
milestones
的行动- 它们将从 user_resolutions#create
填充 Controller Action 。
这有几件事要看。我会在这里详细介绍一些。这不是一个具体的答案,但可能会帮助您指明正确的方向。
首先,您需要确保收到正确的参数。
Cocoon
构建嵌套表单做得很好——您需要确保它符合 Rails 的嵌套属性结构。
为此,您应该right-click > view source
.
在f.fields_for
部分(在 HTML 中不会这样称呼),您将查找与以下内容等效的内容:
<input type="text" name="milestones_attributes[0][name]" value="">
需要注意的重要一点是名字...
每次您为此使用表单或任何 Rails View 助手时,您真的只是在构建标准的 HTML。 form_for
只是创建一个 HTML 表单,因此其中包含的任何参数都需要遵循特定的结构,以便 Rails 识别这些参数。
f.fields_for
元素通常称为 x_attributes[:id][:param]
- 这被传递给 Rails,它循环遍历每个 [:id]
确定要添加的嵌套参数的数量。
以上命名结构需要查一下出处。如果你看到它,那很好。如果不是,则表示您没有正确构建表单。
其次,您需要确保在 Controller 中构建您的对象。
我不确定如何 Cocoon
这样做,但本质上,每次你使用 f.fields_for
,您必须先构建关联对象:
def new
@user_reservation = UserReservation.new
@user_reservation.milestones.build #-> this is what makes f.fields_for work
end
如果第一步显示不正确的元素命名,则意味着您的关联对象未构建(这就是它们未被识别的原因)。
要测试它,您应该在发送之前在 new 方法中构建关联对象。
最后,您需要发布您的参数。
这些详细地告诉您 Rails 对嵌套属性做了什么,使您能够确定它们发生了什么。
抱歉冗长的回答。反正你不会收到任何答复,所以我觉得给你一些东西是明智的。
关于ruby-on-rails - 表单提交时未添加嵌套字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33454262/