Ensuring a column is unique for an entity in Rails
In a previous article, we talked about guaranteeing unique values for a database column in Rails. Today let's expand upon that and see how we can do the same, but not across the entire table.
For example, let's say we have a table of Article
s that belong to a User
:
class Article < ApplicationRecord
belongs_to :user
end
class User < ApplicationRecord
has_many :articles
end
and that we want to guarantee that each article for a given user has a unique title
. In other words, Bob and Sally can both write articles titled "How to Adopt a Retired Racing Greyhound" but neither of them can write two articles with that title.
Validating at the ORM level with ActiveRecord
Validating this in our Rails model is pretty straight forward.
class Article < ApplicationRecord
belongs_to :user
validates :title, uniqueness: { scope: :user_id }
end
This scopes our uniqueness
validation to values that are unique for the record's user_id
.
Ensuring uniqueness at the database level
Adding database-level protections for this feature involves creating a unique index that is based on multiple columns (title
and user_id
):
class AddUniqueIndexForArticleTitlesAndUserIds < ActiveRecord::Migration[6.0]
def change
add_index :articles, [:title, :user_id], unique: true
end
end
And there you have it! Your records will be properly validated, and uniquely scoped to each user.