2009-06-17 107 views
2

更具体地说,“如何验证模型是否至少需要创建x个有效的关联模型?”。我一直在尝试验证嵌套模型,它们是以与父代相同的形式创建的(并最终显示立即验证la jQuery)。作为一个流行的例子,让我们假设以下模型和模式。验证嵌套模型?

class Project 
    include DataMapper::Resource 

    property :id,  Serial 
    property :title, String, :nullable => false 

    has 2..n, :tasks 
end 

class Task 
    include DataMapper::Resource 

    property :id,   Serial 
    property :project_id, Integer, :key => true 
    property :title,  String, :nullable => false 

    belongs_to :project 
end 

所有验证都在模式定义中完成,如您所见。这里最重要的是“has 2..n, :tasks”。考虑到params散列中的嵌套任务属性将产生有效的任务,此验证实际上正常工作。但是,如果他们产生了无效的任务,那么该任务将不会被创建,并且最终会得到一个项目少于2个任务,因此会产生项目对象无效的

据我所知,这是因为它不能确定任务属性是否有效,直到它试图保存任务,并且因为 - 据我所知 - 任务不能在项目之前得到保存,项目不知道这些任务是否有效。我认为这是否正确?

无论如何,我希望能有一个快速的答案,但似乎没有那么微不足道,我希望。如果你有任何建议,那将不胜感激。

回答

2

我实际上在DataMapper中使用事务找到了一个很好的解决方案。基本上这个事务试图保存父对象以及所有的子对象。一旦保存失败,交易就会停止,并且不会创建任何内容。如果一切顺利,则对象将成功保存。

class Project 
    def make 
    transaction do |trans| 
     trans.rollback unless save 
     tasks.each do |task| 
     unless task.save 
      trans.rollback 
      break 
     end 
     end 
    end 
    end 
end 

这可以确保在任何事情得到保存之前,一切都是有效的。我只需要将我的#save和#update方法更改为#在我的控制器代码中生成。

0

如果您的数据库引擎支持SET CONSTRAINTS DEFERRED可能会很有用。

否则,也许编写一个存储过程来执行插入操作,然后说它的存储过程的可靠性,以确保只插入正确的,经过验证的数据。

+0

感谢克里斯,这些都是很好的建议,虽然我不是在寻找特定于数据库的解决方案。我希望逻辑和验证保持在应用程序本身内。如果最差的情况最糟糕,我只会写一个保存后钩来验证记录(丑陋,我知道,但可能是唯一明智的方法)。 – 2009-06-18 20:34:28

0

有一个模型方法valid?在模型对象保存之前运行验证。因此,验证关联的简单方法是使用validates_with_block' or 'validates_with_method来检查关联上的验证。

这将是这个样子

validates_with_block do 
    if @tasks.all?{|t|t.valid?} 
    true 
    else 
    [false, "you have an invalid task"] 
    end 
end 

或者你可以看看dm-association-validatordm-accepts-nested-attributes

编辑:额外的疯狂。对任务运行验证,然后检查唯一的错误是否与关联有关。

validates_with_block do 
    if @tasks.all?{|t|t.valid?;!t.errors.any?{|e|e[0]==:project}} 
    true 
    else 
    [false, "you have an invalid task"] 
    end 
end 
+0

不幸的是,所有任务在那时都是无效的,因为它们还没有被保存(ID => nil,project_id => nil等),所以验证总是返回false。这是问题所在,因为父AND子项同时以相同的形式创建。 – 2009-06-21 07:56:16

+0

我也试过没有运气的dm-accep_nested_attributes。我在IRC与snusnu(插件作者)聊过,似乎无法弄清楚。这是一个已知的问题,但似乎是一个灰色地带。 – 2009-06-21 08:06:16