我有一个模型Tag
,并且可能存在多个Tag
s的层次结构:即某些Tag
可能是另一个标记的超级或子标记,因此上。
注意:不一个大标签树;它只是许多单个标签,有时一个标签是另一个或多个标签的超级标签。它已经很好了。
每个Tag
也belongs_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还没有类似的支持。但是,做我需要的最佳做法是什么?目前我只是禁用了这个验证,但我真的不喜欢这个“解决方案”。
答案 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
中讨论过