【发布时间】:2013-04-23 10:23:20
【问题描述】:
为了使嵌套属性的验证在我的 rails 应用程序中工作,我一直在苦苦挣扎。一个小警告是,我必须根据父级的属性动态验证嵌套属性,因为所需的信息量会根据父级在进程中的位置随时间而变化。
这是我的设置:我有一个具有许多不同关联模型的父级,我想在每次保存父级时验证这些模型的后续嵌套属性。鉴于验证是动态变化的,我不得不在模型中编写一个自定义验证方法:
class Parent < ActiveRecord::Base
attr_accessible :children_attributes, :status
has_many :children
accepts_nested_attributes_for :children
validate :validate_nested_attributes
def validate_nested_attributes
children.each do |child|
child.descriptions.each do |description|
errors.add(:base, "Child description value cant be blank") if description.value.blank? && parent.status == 'validate_children'
end
end
end
end
class Child < ActiveRecord::Base
attr_accessible :descriptions_attributes, :status
has_many :descriptions
belongs_to :parent
accepts_nested_attributes_for :descriptions
end
在我的控制器中,当我想保存时,我在父级上调用 update_attributes。现在的问题是,显然,rails 针对数据库而不是针对用户或控制器修改的对象运行验证。所以可能发生的情况是,孩子的值被用户删除了,验证会通过,而后来的验证不会通过,因为数据库中的项目无效。
下面是这个场景的一个简单示例:
parent = Parent.create({:status => 'validate_children', :children_attributes => {0 => {:descriptions_attributes => { 0 => {:value => 'Not blank!'}}}})
#true
parent.update_attributes({:children_attributes => {0 => {:descriptions_attributes => { 0 => {:value => nil}}}})
#true!! / since child.value.blank? reads the database and returns false
parent.update_attributes({:children_attributes => {0 => {:descriptions_attributes => { 0 => {:value => 'Not blank!'}}}})
#false, same reason as above
验证适用于一级关联,例如如果 Child 具有“值”属性,我可以按照我的方式运行验证。问题在于,在保存之前显然无法验证深层关联。
谁能指出我如何解决这个问题的正确方向?我目前看到的唯一方法是保存记录,然后验证它们并在验证失败时删除/恢复它们,但老实说,我希望有更干净的东西。
提前谢谢大家!
解决方案
事实证明,我通过在自定义验证中直接引用深层嵌套模型来运行验证,这样:
class Parent < ActiveRecord::Base
[...]
has_many :descriptions, :through => :children
[...]
def validate_nested_attributes
descriptions.each do |description|
[...]
end
end
end
由于某种原因,这导致了我在上面遇到的问题。感谢 Santosh 测试我的示例代码并报告它正在工作,这为我指明了正确的方向来解决这个问题。
为了将来参考,原始问题中的代码适用于这种动态的、深度嵌套的验证。
【问题讨论】:
-
您的代码中几乎没有错误。可能是错字。 1. '子值不能为空' -- 单引号内的单引号。 2. && parent.status = 'validate_children' -- 这不是比较。它的任务
-
抱歉有错别字!这里的代码只是我的应用程序的一个简化示例,所以这不是它不起作用的原因,但感谢您指出这一点:)
标签: ruby-on-rails validation nested