Search code examples
ruby-on-railsrubyrails-activerecord

Rails: Ensure only one boolean field is set to true at a time


I have a model that has fields of name:string, default:boolean. I want the true value to be unique so that only one item in the database can be set to true at once. How do I set my update and new actions in my controller to set all the rest of the values of items to false?

Let's say I have the following setup in my database

name:string | default:boolean |  
Item1       | true            |  
Item2       | false           |  
Item3       | false           |  

If I change Item2 default value to true, I want it to loop through all items and set the rest of them to false, so only one is true at once, so it looks like this.

name:string | default:boolean |  
Item1       | false           |  
Item2       | true            |  
Item3       | false           | 

Solution

  • This code is stolen from previous answer and slightly simplified:

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

    You can use this method in before_save callback in your model.

    Actually, it is better to "falsify" only records which values are 'true', like this:

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

    UPDATE: to keep code DRY, use self.class instead of Item:

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