验证嵌套表单中子对象的唯一性无法正常工作

时间:2012-03-14 16:01:55

标签: ruby ruby-on-rails-3 validation

我在Rails中的作用域唯一性验证有问题。如果我尝试使用我不想重复的相同属性集创建一个具有直接在子模型中的新对象,但是当我尝试创建具有两个不唯一的子节点的父对象时,它可以正常工作没有被触发。

背景

我在Rails 3.2中有一个应用程序,其在HAML中的视图使用simple_form。

我有两个模型:PageProperty。页面可以包含许多属性,并且它接受属性的嵌套属性。

我想验证一个页面不能有两个具有相同名称的属性:

#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属性。

就像我说的,当通过其表单创建新属性时,验证工作正常。如果我尝试创建一个具有相同名称和相同page_id的新属性,Rails会告诉我该名称已被删除。

问题

如果我创建一个新的页面,并通过嵌套的表单,分配各种属性,我可以绕过此验证。当数据库中尚未存在page_id和property_id的组合时,这似乎只是一个问题,例如,如果我编辑已保存属性的Page模型,并且我尝试添加一个新的一个同名,验证现在触发。

1 个答案:

答案 0 :(得分:3)

我会尝试使用validates_associated

class Page < ActiveRecord::Base
  has_many :properties
  accepts_nested_attributes_for :properties, :allow_destroy => :true
  validates_associated :properties 
end

<强>更新

有关验证状态的Rails指南:

  

通过在模型中执行SQL查询来进行验证   表,搜索具有相同值的现有记录   属性。

您正在创建的2 Properties对象在数据库中尚不存在,因此唯一性验证无法正常工作。您应该尝试使用自定义验证

class Property < ActiveRecord::Base
  #...
  validate :name, :name_uniqueness

  def name_uniqueness 
    self.page.properties.select {|p| p.key == self.key}.size == 1
  end
end