验证嵌套形式中子对象的唯一性无法正常工作 [英] Validate uniqueness of a child object in a nested form not working correctly
问题描述
Rails 中的作用域唯一性验证有问题.如果我尝试直接在子模型中创建一个具有我不想重复的相同属性集的新对象,它工作正常,但是当我尝试创建一个具有两个不唯一的子项的父项时,验证未触发.
I have a problem with the scoped uniqueness validation in Rails. It works fine if I try to create a new object with the same set of attributes that I don't want to repeat, directly in the child model, but when I try to create a parent with two childs that are not unique, the validation is not triggered.
我在 Rails 3.2 中有一个应用程序,其视图在 HAML 中使用 simple_form.
I have an application in Rails 3.2, with its views in HAML with simple_form.
我有两个模型:Page
和 Property
.一个页面可以有多个属性,并且它接受属性的嵌套属性.
I have two models: Page
and Property
. A page can have many properties, and it accepts nested attributes for property.
我想验证一个页面不能有两个同名的属性:
I want to validate that a Page must not have two properties with the same name:
#app/models/page.rb
class Page < ActiveRecord::Base
has_many :properties
accepts_nested_attributes_for :properties, :allow_destroy => :true
end
#app/models/property.rb
class Property < ActiveRecord::Base
belongs_to :page
VALID_PROPERTIES = %w(id text name xpath class css)
validates :name, :inclusion => VALID_PROPERTIES, :uniqueness => {:scope => :page_id}
end
当然,该属性有一个 page_id 属性.
Of course, the property has a page_id attribute.
就像我说的,通过表单创建新属性时,验证有效.如果我尝试创建一个具有相同名称和相同 page_id 的新属性,Rails 会告诉我该名称已被占用.
Like I said, when creating a new property via its form, the validation works. If I try to create a new property with the same name and the same page_id, Rails tells me that the name has already been taken.
如果我创建一个新页面,并通过嵌套表单分配各种属性,我可以绕过此验证.当数据库中不存在 page_id 和 property_id 的组合时,这似乎只是一个问题,例如,如果我编辑一个已保存属性的 Page 模型,并尝试添加一个新的同名,验证现在触发.
If I create a new Page, and via nested forms, assign various properties, I am able to bypass this validation. It appears to be only a problem when a combination of page_id and property_id aren't already present in the database, so for example if I edit a Page model, which already has a property saved, and I try to add a new one with the same name, the validation now triggers.
推荐答案
我会尝试 validates_related
:
I would try with validates_associated
:
class Page < ActiveRecord::Base
has_many :properties
accepts_nested_attributes_for :properties, :allow_destroy => :true
validates_associated :properties
end
更新
有关验证状态的 Rails 指南:
The Rails guide on validation states:
验证通过对模型的 SQL 查询执行表,在该表中搜索具有相同值的现有记录属性.
The validation happens by performing an SQL query into the model’s table, searching for an existing record with the same value in that attribute.
您正在创建的 2 个 Properties
对象在数据库中尚不存在,因此无法进行唯一性验证.您应该尝试使用自定义验证
The 2 Properties
object that you're creating do not exists yet in the database, so the uniqueness validation can't work. You should try with a custom validation
class Property < ActiveRecord::Base
#...
validate :name, :name_uniqueness
def name_uniqueness
self.page.properties.select {|p| p.key == self.key}.size == 1
end
end
这篇关于验证嵌套形式中子对象的唯一性无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!