0

我有一个带有父模型的 Rails 表单和另一个模型的可能多个子节点的嵌套属性。

子模型有一个属性,该属性在逻辑中作为数组进行操作,但使用 Rails 内置的序列化方法序列化为 YAML 字符串。

在表单中,我显示了数组的每个单独成员,以便用户可以有选择地删除成员。

当用户销毁所有成员时,就会出现问题。表单不会将参数的任何值传递给 Rails 控制器,当调用 UPDATE 操作时,它会忽略该属性,因为在表单参数哈希中没有它的键。这当然是复选框之类的已知问题,因此 Rails 自动为每个复选框放置 2 个复选框 HTML 元素,一个隐藏的仅在复选框被选中时处理。

我在这里处理的不是复选框,而是隐藏的输入文本字段。

我实现的解决方案是直接在控制器的 UPDATE 操作中操作 params 哈希,如下所示:

params[:series][:time_slots_attributes].each { |k,v| v[:exdates] ||= [] }

这被认为是代码气味吗?

我是否应该添加一个额外的隐藏字段,该字段已禁用并且仅在用户删除最后一个成员时才启用?这个解决方案也很有效,但对我来说似乎很笨拙。

4

2 回答 2

1

这在 NestedAttributes 模块中通过允许“_destroy”参数触发对该特定嵌套属性的销毁调用来处理:

http://apidock.com/rails/ActiveRecord/NestedAttributes/ClassMethods/accepts_nested_attributes_for

如果您不使用嵌套属性(您可能应该使用嵌套属性,在很多情况下它都非常简洁),那么是的,您必须自己手动处理一些东西,通过计算应该存在哪些值并做一些特殊的事情那些。

于 2012-07-13T17:46:34.370 回答
0

这远不是一个详尽的答案......但是在考虑了这个问题之后,我可以看到的一个问题是,如果构建利用相同 UPDATE 操作的未来表单,则会发生意外行为,这违反了最小意外原则。如果稍后构建第二个表单,它不希望更改 exdates 属性的值(因为它没有传递它们),则 UPDATE 操作无论如何都会将一个空数组写入该属性。

我决定通过添加一个具有真正布尔值的隐藏表单字段来解决此问题,然后在将所有时隙 exdates 设置为空数组之前检查该值。这样,如果未来的开发人员创建了一个利用系列控制器的 UPDATE 操作的新表单,他们将不会遇到将 exdates 设置为空数组的意外行为。如果他们想在他们的表单中处理 exdates,他们需要具有相同的隐藏表单字段和真值。这似乎是一个更简单的解决方案,然后为 exdates、migration 和 AR 关联添加一个类和表,并添加另一层嵌套属性,这样我不仅有父子属性,还有父子、子孙和孙子。

于 2012-07-13T17:42:51.797 回答