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