Rails 3 app model如何确保一次只将一个布尔字段设置为true

rue*_*ghn 15 ruby ruby-on-rails

我有一个Logo模型,其字段名称为:string,default:boolean.我希望真值是唯一的,因此数据库中只有一个项可以一次设置为true.如何在我的控制器中设置更新和新操作以将我的徽标的所有其余值设置为false?

假设我的数据库
模型徽标
名称中包含以下设置:string | 默认值:布尔值|
Item1 | 是的|
Item2 | 假|
Item3 | 假|

如果我将Item2默认值更改为true,我希望它循环遍历所有徽标并将其余徽标设置为false,因此一次只有一个是真的,所以它看起来像这样.

name:string | 默认值:布尔值|
Item1 | 假|
Item2 | 是的|
Item3 | 假|

在此先感谢您的帮助.

den*_*lin 21

此代码从之前的答案中被盗,并略有简化:

def falsify_all_others
  Item.where('id != ?', self.id).update_all("default = 'false'")
end
Run Code Online (Sandbox Code Playgroud)

您可以在模型中的before_save回调中使用此方法.

实际上,最好只"伪造"哪些值是'真'的记录,如下所示:

Item.where('id != ? and default', self.id).update_all("default = 'false'")
Run Code Online (Sandbox Code Playgroud)

更新:保持代码DRY,使用self.class而不是Item:

self.class.where('id != ? and default', self.id).update_all("default = 'false'")
Run Code Online (Sandbox Code Playgroud)

  • 使用标准sql为id比较''id <>?'`更好.如果default的当前值也为true,请确保仅启动update_all. (3认同)

Phi*_*lip 5

我认为在你伪造别人之前检查你保存的那个是否真实是件好事.否则,当您保存未激活的记录时,您会伪造所有人.

def falsify_all_others
    if self.default
        self.class.where('id != ? and default', self.id).update_all("default = 'false'")
    end
end
Run Code Online (Sandbox Code Playgroud)