I have been following this tutorial, http://ruby.railstutorial.org/chapters/modeling-users?version=3.2#top, which I find great, but it mentions something about the uniqueness attribute which I don’t get.
This is mu user file so far:
class User < ActiveRecord::Base
#these attributes can be modified by the users
attr_accessible :name, :email;
#validation testing
validates :name, presence: true, length: { maximum: 50 }
#regular expression (there is an official one)
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
#and add it..
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
end
It says:
” Using validates :uniqueness does not guarantee uniqueness.
Alice accidentally clicks on “Submit” twice, sending two requests in quick succession.
The following sequence occurs: request 1 creates a user in memory that passes validation, request 2 does the same, request 1’s user gets saved, request 2’s user gets saved.
Result: two user records with the exact same email address, despite the uniqueness validation.”
I tried creating 2 users with the same email address using the console, (and the User.create method), and uniqueness seemed to work fine since only the first one got into sqlite3. So what could cause an error or uniqueness to fail?
I believe the point the tutorial is trying to make is that the uniqueness validation is enforced by the application layer, not by the database. If you had a system that could handle multiple requests simultaneously, the :uniqueness validation suffers from what is known as a race condition.
The way uniqueness works is to (1) query the database for a matching record. If a matching record is not found, then validation passes and (2) the record is saved to the database. Between steps (1) and (2), it is theoretically possible, although unlikely, for another request to swoop in and add a matching record to the database.
The problem can be avoided by also enforcing uniqueness in the database. How to do that is dependent on the database you are using; Rails does not assist you in doing so.