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

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

假设我的数据库中有以下设置
模型标志
name:string | 默认值:布尔值|
Item1 | 是的|
Item2 | 假|
Item3 | 假|

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

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

在此先感谢您的帮助。

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

def falsify_all_others Item.where('id != ?', self.id).update_all("default = 'false'") end 

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

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

 Item.where('id != ? and default', self.id).update_all("default = 'false'") 

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

 self.class.where('id != ? and default', self.id).update_all("default = 'false'") 

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

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

在您的控制器代码中,您可以执行以下操作….请注意您可能将Item2作为参数[…],以便您可以在下面进行交换

 @items_to_be_falsified = Item.where('id != ?', Item2.id) @items_to_be_falsified.each do |item| item.default = false item.save end 

请注意,当你完成这项工作时,将它移到模型中的好习惯是,将它变成一个函数并调用它像Item2.falsify_all_others如下所示

 def falsify_all_others Item.where('id != ?', self.id).each do |item| item.default = false item.save end end 

请享用!

我还建议伪造你的所有记录然后让它们成真。

 add_column :users, :name ,:boolean, default: false 

好的还有一些你需要的东西。

不要使用字段名称default,它通常是为数据库保留的。 保存默认为false的记录会将所有记录设置为false,这不是您想要的。 检查我们是否将此记录设置为true和falseify。

  before_save :falsify_all_others def falsify_all_others if is_default self.class.where('id != ?', self.id).where('is_default').update_all(:is_default => false) end end 

如果你想要这个用于创建和更新(rails v4),请记下rails指南中的这个花絮

after_save在创建和更新时运行,但总是在更具体的回调after_create和after_update之后运行,无论宏调用的执行顺序如何。