I’m currently going through the Ruby on Rails Tutorial by Michael Hartl and learned something important about the uniqueness
validation argument on the validates
method. First of all, the validates
method is provided by Active Record and allows you to impose constraints on model attributes. For example, let’s say you have a User model and one of it’s attributes is a user’s email address. Well the uniqueness
validation argument enforces that every email submitted to the database must be unique. It’s obvious why this is an important constraint to enforce when creating a web app. But there’s a problem; If a user mistakenly submits a sign-up form twice, Rails will still create two different users with the same attributes despite the uniqueness
validation. What I learned is that in order to solve this you must also enforce uniqueness
at the database level by creating a database index on the email column and require that the index be unique. Going through the tutorial, I first generated a migration to add structure to the existing User model:
I then opened up the migration file and included the add_index
method to add an index on the email column of the users table and enforced uniqueness:
Don’t forget to run the migration when you’re done:
There’s still one more step; we have to make sure that the email attribute gets saved into the database as all lowercase in order for this to work. This is because not all database adapters use case-sensitive indices. So the way to do this is by writing the before_save
callback method in the User model and pass a block that sets the user’s email to all downcase using the downcase
string method:
Now we can rest assured that the uniqueness
validation will enforce that each user has a unique email address!