Given the following model and migration that creates it, what might we want to add?
# app/modes/user.rb
class User < ActiveRecord::Base
validates :email, uniqueness: true
end
# db/20150527181920_create_users.rb
class CreateUsers < ActiveRecord::Migration
create_table :users do |t|
t.string :email
t.timestamps null: false
end
end
We would want to add a unique constraint on the email column in addition to the uniqueness validation. Although the uniqueness validation in the model will provide some protection and useful error messages, the minute your application has two servers running simultaneously (which is recommended for all production applications), any request might run into a race condition in which two application servers are both trying to create the record. If they are timed closely enough, both will create a record with the same email address.
A database constraint provides a stronger uniqueness guarantee. This is done with a unique index, which has the benefit of being nice and fast!
# db/20150527181920_create_users.rb
class CreateUsers < ActiveRecord::Migration
create_table :users do |t|
t.string :email
t.timestamps null: false
end
add_index :users, :email, unique: true
end
Note we still want to keep the validation in the model as it provides user-facing error messages in forms, as well as documenting this constraint in the code. This is a case where we don't want to be too DRY.
Check out the Giant Robots post on [The Perils of Uniqueness Validations][]
[The Perils of Uniqueness Validations]: https://robots.thoughtbot.com/the-perils-of-uniqueness-validations
Return to Flashcard Results