There can only be one...
August 19, 2020
Use case: For a given database table with a table column storing boolean values, we only want to allow a single row to be true or false - for example, a Games table where only 1 game can be active at a time. We can use Active Record validations to constrain the truthy value to a single row.*
# == Schema Information
#
# Table name: games
#
# id :bigint
# name :string
# description :string
# active :boolean
class Game < ApplicationRecord
validates_uniqueness_of :active, if: :active?
end
This is essentially saying, “If the value in the active
column is true (if: :active?
), then make sure it’s the only
one (validates_uniquess_of
)“.
It can also be expanded and scoped, i.e. “There can only be 1 active game at a venue”:
# == Schema Information
#
# Table name: game_venue
#
# id :bigint
# game_id :string
# venue_id :string
# active :boolean
class GameVenue < ApplicationRecord
validates_uniqueness_of :active, scope: :venue_id, if: :active?
end
“For a given game at a particular venue, make sure it is the only active one”. Now, if we try to create two active GameVenue records, ActiveRecord will raise an error:
venue = Venue.first
game_venue_1 = GameVenue.create(venue_id: venue.id, active: true)
# valid
game_venue_2 = GameVenue.create(venue_id: venue.id, active: true)
# ActiveRecord::RecordInvalid - Active has already been taken