我正在努力让自己的头脑对这个问题感兴趣,所以我希望我能够很好地解释它。我有一个嵌套模型的表单。一个简化版本的东西如下(使用Rails 3.0.13);在Rails更新验证失败后未被破坏的嵌套属性
#parent.rb
class Parent < ActiveRecord::Base
has_many :children, :dependent => destroy
accepts_nested_attributes_for :children, :allow_destroy => true
validates_presence_of :thing
validate :children_unique
def children_unique
errors[:base] << "You have the same child listed more than once!" if self.children.map{|x| [child.name, child.age]} != self.children.map{|x| [child.name, child.age]}.uniq
end
end
#child.rb
class Child < ActiveRecord::Base
belongs_to :parents
end
#parents_controller.rb
class ParentsController < ApplicationController
load_and_authorize_resource :parent #Using cancan for authorization. This calls @parent = Parent.find(params[:id]); authorize! :update, @parent; at the start of the update method
def update
if @parent.update_attributes(params[:operation])
redirect_to @parent.admission, :notice => 'Operation was updated successfully'
else
flash.now[:warning] = "Parent was NOT updated!"
render :action => "edit"
end
end
end
到目前为止都是非常标准的。我的表单也以相当标准的方式建立。我打电话给parent_form.fields_for :children
,并在fields_for块中为子女提供部分内容。每个子部分表单包含一个删除链接,并且当它被点击时,javascript用于设置一个隐藏字段,因此_destroy的属性设置为“1”,并且该部分从视图中隐藏。
这在大多数情况下效果很好,但我发现的奇怪问题如下;
如果我正在编辑一个已经有2个孩子的现有父母,并删除其中的1个孩子,然后将'thing'设置为空,则表单无法按预期验证(因为'thing'不存在)并且编辑视图被重新渲染。在结果看来,我删除的孩子再次出现!其隐藏的_destroy字段设置为“true”,如果我再次填写“thing”并提交表单,则更新的父级只有1个子级。
我通过向嵌套的子div div <div class='fields'<%= " style='display: none;'" if f.object._destroy %>>
添加条件样式标记来处理此问题,因此如果在尝试更新记录之前将其删除,它将不再显示。这实现了它的目标,但是,如果我这样做并提交表单而不纠正空的'thing'字段,以便模型再次验证失败,并且在出现的下一个编辑表单中添加一个与之前删除的子项相同的新子项并填写'thing'字段,即使第一个相同的子项的_delete属性设置为“true”,模型现在也会失败children_unique
验证。
很明显,我已经把自己绑在这里,我已经尝试了大量的替代方法和修改,这是我迄今为止最好的。这是非常非常接近的,但我仍然有这种奇怪的边缘情况下,实际上可能永远不会发生,但这表明我不太了解我的控制器和模型的交互方式。
有人可以设置我吗?
这是一个好主意 - 我真的希望不要下井AJAX途径在这个应用程式所有,但它会解决这个问题。 – brad
您可以在更新操作开始时在控制器中使用AJAX。 – user2340939