如何最多允许一个rails模型的记录具有bool属性为true?

Ana*_*and 1 activerecord ruby-on-rails

在典型的Rails(4.2.x)博客应用程序中,我有一个Post模型。该帖子具有一个称为primary的布尔列。我想强制执行一个模型级别的约束,即至多一个帖子具有primary = true。如果用户将新帖子设置为primary = true,则在保存此帖子之前,所有其他帖子都必须标记为primary = false。

当帖子创建或更新为primary = true时,我可以在控制器中执行此操作,方法是将所有其他帖子更改为primary = false。就像是:

# in posts_controller#create and #update
...
if @post.primary
  [Post.all - self].select(&:primary).each do {|p|p.primary = false; p.save}
end
@post.save!
...
Run Code Online (Sandbox Code Playgroud)

但是,我希望这是一个模型级别的约束,因此我可以添加验证,单元测试等,以确保只有一个帖子具有primary = true。如果我使用类似before_commit的回调,那么我可能会陷入无限循环,因为更新新帖子的before_commit中的旧帖子会触发旧帖子的before_commit等。

如何在模型级别强制执行此行为?

Van*_*Huy 6

ActiveRecord的有一些更新的属性不触发回调等的方法post.update_columnPost.update_all等等。所以,你可以像一个回调使用这些

before_save :set_primary

private
def set_primary
  Post.where.not(id: id).update_all(primary: false)
end
Run Code Online (Sandbox Code Playgroud)