后端:我有一个模型(用户),其中包含另一个模型(ContactPreference)。 前端:允许用户重新排序,添加和删除特定用户的联系首选项的界面。
我想让用户使用单个表单提交一次性提交所有更改。我现在这样做的方式是在User模型中使用allows_nested_attributes_for :contact_preferences
,并天真地POST属于已编辑的首选项列表的属性。除了明显的错误之外,它的工作正常:如果用户删除了联系人首选项,则不会发送ID,并且不会从数据库中删除首选项。
allows_nested_attributes_for
支持从集合中删除对象,但它要求客户端跟踪已删除的ID并传递'_destroy' => 1
参数。这是我宁愿避免的混乱逻辑;我只想删除对象,除非它们明确包含在参数中。据我所知,allows_nested_attributes_for
不支持此行为,所以我希望实现自己的解决方案。
最有效(在数据库访问方面)进行此类更新的方法是什么?我是否删除所有内容并从头开始重建列表?我是否加载关联并挑选未明确包含的对象?也许我可以使用一些聪明的ActiveRecord魔法?
答案 0 :(得分:1)
我个人的感觉是,使用:destroy => 1
标志进行此操作时,设置方式比其他选项要简单得多。另一种方法是在服务器上加载关联,比较传入的参数,找出丢失的记录,然后删除丢失的记录并更新剩余的记录。这是一个额外的逻辑,数据库操作,最糟糕的是,你将不得不手工修改accepts_nested_attributes_for
,这是一个非常重要的壮举。
HTML给你一个小技巧/黑客来完成这个没有JS。为名称为:destroy
的每条记录添加一个复选框。使用高级表单助手,例如check_box
,而非check_box_tag
(需要手动完成很多事情),或更高级别的表单助手,例如simple_form gem。
如果未选中该标志,则HTML将不会提交任何内容,并且记录将保留。如果选中该标志,HTML将提交:destroy
标志,并且将使用内置的服务器端机制将其删除。
你没有多说你的前端代码;听起来你在那里有一堆JS。您可能在用户“删除”它时隐藏记录,如果您不想使用上面的复选框方法,则可以在这种情况下以编程方式添加destroy
标志。与试图猜测后端行为相比,这将更简单,更不容易出错。