我有一个带有父模型的Rails表单和另一个模型的潜在多个子项的嵌套属性。
子模型有一个属性,它在逻辑中作为数组进行操作,但使用Rails内置的序列化方法序列化为YAML字符串。
在表单中,我显示数组的每个成员,以便用户可以有选择地删除成员。
当用户销毁所有成员时,就会出现问题。表单不会将param的任何值传递给Rails控制器,并且当调用UPDATE操作时,它会忽略该属性,因为表单params hash中没有键。这当然是复选框之类的已知问题,因此Rails会自动为每个复选框添加2个复选框HTML元素,其中一个隐藏只有在选中复选框时才会处理。
我不是在处理复选框,而是隐藏输入文本字段。
我实现的解决方案是直接在控制器的UPDATE操作中操作params哈希,如下所示:
params[:series][:time_slots_attributes].each { |k,v| v[:exdates] ||= [] }
这被认为是代码味道吗?
我是否应该添加一个禁用的额外隐藏字段,并且仅在用户删除最后一个成员时才启用?这个解决方案也有效,但对我来说似乎很笨拙。
答案 0 :(得分:1)
这在NestedAttributes模块中通过允许“_destroy”参数触发针对该特定嵌套属性的destroy调用来处理:
http://apidock.com/rails/ActiveRecord/NestedAttributes/ClassMethods/accepts_nested_attributes_for
如果你没有使用嵌套属性(你可能应该这样,在很多情况下都非常简洁)那么是的,你必须自己动手一些东西,通过计算应该>的值已经出席并为这些人做了特别的事。
答案 1 :(得分:0)
这远不是一个详尽的答案......但在考虑了这个问题之后,我可以看到的一个问题是,如果构建了利用相同UPDATE操作的未来表单,则会发生意外行为,这违反了至少原则惊喜。如果稍后构建了第二个表单,它不希望更改exdates属性的值(因为它没有传递它们),UPDATE操作将无论如何都会在属性中写入一个空数组。
我决定通过添加一个带有true布尔值的隐藏表单字段来解决此问题,然后在将所有时隙exdates设置为空数组之前检查此值。这样,如果未来的开发人员创建了一个利用系列控制器的UPDATE操作的新表单,他们就不会将其exdates的意外行为设置为空数组。如果他们想要以他们的形式处理exdates,他们需要具有相同的隐藏表单字段并具有真值。这似乎是一个更简单的解决方案,然后为exdates,migration和AR关联添加一个类和表,并添加另一层嵌套属性,这样我不仅有父和子属性,还有父,子和孙子。这个解决方案有点像Rails hack,用于处理表单中第二个隐藏复选框字段的复选框。