Rails 3从表单数据重建嵌套属性

问题描述:

后端:我有一个模型(用户)has_many的另一个模型(ContactPreference)。 前端:允许用户重新排序,添加和删除特定用户的联系人首选项的界面。Rails 3从表单数据重建嵌套属性

我想让用户一次性完成所有更改并使用单一表单提交。我现在这样做的方式是在用户模型中使用allows_nested_attributes_for :contact_preferences,并且天真地发布已编辑的首选项列表的属性。除了一个明显的缺陷外,它工作得很好:如果用户删除联系人首选项,则不会发送该ID,并且该首选项不会从数据库中删除。

allows_nested_attributes_for支持从集合中删除对象,但它要求客户端跟踪哪些ID已被删除并通过'_destroy' => 1参数。这是凌乱的逻辑,我宁愿避免;我只想删除对象,除非它们明确包含在参数中。据我所知,allows_nested_attributes_for不支持这种行为,所以我正在寻求实施我自己的解决方案。

什么是最有效的(在数据库访问方面)做这种更新的方式?我是否删除所有内容并重新构建列表?我是否加载关联并挑出未明确包含的对象?也许我可以使用一些聪明的ActiveRecord魔法?

我个人的感觉是,使用:destroy => 1标志这样做的设置比其他选择要少得多。另一种方法是在服务器上加载关联,比较传入参数,找出哪些记录丢失,然后删除丢失的记录并更新剩余的记录。这是很多额外的逻辑,数据库操作,并且最糟糕的是,您必须手工重做accepts_nested_attributes_for这是一项不平凡的壮举。

HTML给你一个小技巧/黑客来完成这个没有JS。为名称为:destroy的每条记录添加一个复选框。使用高级表单助手,例如check_box,而不是(需要很多东西才能手动获取)或更高级别的帮助器,例如simple_form gem

如果该标志未被选中,那么HTML将不会提交任何内容,并且该记录将保留。如果该标志被选中,HTML将提交:destroy标志,并且它将被立即删除,并且使用内置的服务器端机制。

您对前端代码没有多说;听起来你在那里有一堆JS。当用户“删除”它时,您可能会隐藏该记录,如果您不想使用上面的复选框方法,则可以在该情况下以编程方式简单地添加destroy标志。与尝试对后端行为进行第二次猜测相比,这会更简单,更不容易出错。