为什么直接操作Rails表单params散列被认为是代码气味



我有一个Rails表单,它有一个父模型和另一个模型的多个子模型的嵌套属性。

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

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

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

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

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

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

这被认为是代码气味吗?

我应该添加一个额外的隐藏字段吗?该字段是禁用的,只有在用户删除最后一个成员时才启用?这个解决方案同样有效,但对我来说似乎很笨重。

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

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

如果你没有使用嵌套属性(你可能应该使用嵌套属性,在很多情况下都很巧妙),那么是的,你必须自己动手,找出哪些值应该存在,并用它们做一些特别的事情。

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

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

相关内容

最新更新