Rails:验证一组项目

时间:2014-01-12 22:05:42

标签: ruby-on-rails validation

我有一个模型Tag,并且可能存在多个Tag s的层次结构:即某些Tag可能是另一个标记的超级或子标记,因此上。

注意:一个大标签树;它只是许多单个标签,有时一个标签是另一个或多个标签的超级标签。它已经很好了。

每个Tagbelongs_to :user

存在约束:层次结构中的所有Tag都应属于同一User。 我试图通过Rails验证系统实现这个约束,但我失败了。让我们看看为什么:

要检查层次结构中每个标记的所有者,我应该在保存之前递归获取特定标记的所有超级和子标记。

假设我们有一个简单的3个标签层次结构:

tag1 -> tag2 -> tag3

这些标签中的每一个都属于同一个用户(例如“user1”)。

有一天,我需要将所有者更改为“user2”。在保存每个标签之前,如果用户通过整个层次结构进行检查,实际上是不可能的。

说,我尝试做这样的事情:

tag1.owner = user2
tag2.owner = user2
tag3.owner = user2

然后保存每个标签。但是当我尝试保存第一个标签时,其他所有标签都没有保存,用户存储在DB中的这些标签是“user1”。验证失败。

解决方案可以是一次保存所有标签(作为单个“事务”),然后检查受此事务影响的所有标签,如果所有标签都有效,则提交事务;否则回滚它。这将是完美的,它可以在语法上看起来像这样:

tag1.owner = user2
tag2.owner = user2
tag3.owner = user2

transaction do
   tag1.save
   tag2.save
   tag3.save
end

就是这样!但是,据我所知,Rails还没有类似的支持。但是,做我需要的最佳做法是什么?目前我只是禁用了这个验证,但我真的不喜欢这个“解决方案”。

1 个答案:

答案 0 :(得分:0)

我不知道最佳做法,但由于没有其他人已经回答并且已经有一段时间了,我想我会发布你可以做的事情:

tag1.owner = user2
tag2.owner = user2
tag3.owner = user2

tag1.transaction do
   tag1.save!
   tag2.save!
   tag3.save!
end

,因为

  • 事务是“按数据库连接”,transaction方法被定义为ActiveRecord::Base
  • 的类和实例方法
  • save不同,save!本身并不包含在交易中

http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html

中讨论过