2010-10-25 24 views
4

我正在使用Rails 2.3.8和accepting_nested_attributes_for。accep_nested_attributes_for验证

我有一个简单的类别对象,它使用awesome_nested_set来允许嵌套的类别。

对于每个类别,我想要一个称为代码的独特字段。这对每个级别的类别都是唯一的。含义父类别将全部具有唯一代码,并且子类别在它们自己的父类别中将是唯一的。

EG:

code name 
1 cat1 
    1 sub cat 1 
2 cat2 
    1 sub cat 1 
    2 sub cat 2 
3 cat3 
    1 sub1 

此作品,未经验证的过程,但是当我尝试使用类似: validates_uniqueness_of:代码:范围=>:PARENT_ID

这不会因为父母工作尚未保存。

这里是我的模型:

class Category < ActiveRecord::Base 
    acts_as_nested_set 
    accepts_nested_attributes_for :children, :reject_if => lambda { |a| a[:name].blank? }, :allow_destroy => true 

    default_scope :order => "lft" 

    validates_presence_of :code, :name, :is_child 
    validates_uniqueness_of :code, :scope => :parent_id 
end 

我曾想过以不同的方式来做到这一点,这是非常接近的工作,问题是我无法检查子类别之间的唯一性。

在第二个示例中,我在名为'is_child'的表单中嵌入了一个隐藏字段来标记该项是否为子类。这是我的例子:

class Category < ActiveRecord::Base 
    acts_as_nested_set 
    accepts_nested_attributes_for :children, :reject_if => lambda { |a| a[:name].blank? }, :allow_destroy => true 

    default_scope :order => "lft" 

    validates_presence_of :code, :name, :is_child 
    #validates_uniqueness_of :code, :scope => :parent_id 
    validate :has_unique_code 

    attr_accessor :is_child 


    private 
    def has_unique_code 

    if self.is_child == "1" 
     # Check here if the code has already been taken this will only work for 
     # updating existing children. 
    else 

     # Check code relating to other parents 
     result = Category.find_by_code(self.code, :conditions => { :parent_id => nil}) 

     if result.nil? 
     true 
     else 
     errors.add("code", "Duplicate found") 
     false 
     end 
    end 
    end 
end 

这非常接近。如果有一种方法可以在rejected_if语法下检测accept_nested_attributes_for中的重复代码,那么我会在那里。这一切似乎都过于复杂,但愿意提供建议以使其更容易。我们希望不断添加类别和子类别,因为它可以加速数据输入。

更新: 也许我应该使用构建或before_save。取而代之的

validates_uniqueness_of :code, :scope => :parent_id 

回答

4

尝试

validates_uniqueness_of :code, :scope => :parent 

除此之外,你需要在Category类设置:

has_many :children, :inverse_of => :category # or whatever name the relation is called in Child 

使用inverse_of会使孩子变在保存之前设置为parent,并且有可能工作。

+0

谢谢!我一直在尝试使用父对象的值作为验证的一部分来验证嵌套字段。由于父对象不可用,因此新对象失败。 :inverse_of声明使它工作! – 2012-12-14 19:06:00