validates_uniqueness_of :name, :case_sensitive => false
thực hiện thủ thuật, nhưng bạn cần lưu ý rằng điều validates_uniqueness_of
đó không đảm bảo tính duy nhất nếu bạn có nhiều máy chủ / quy trình máy chủ (ví dụ: chạy Phusion Passenger, nhiều Mongrels, v.v.) hoặc máy chủ đa luồng. Đó là bởi vì bạn có thể nhận được chuỗi sự kiện này (thứ tự là quan trọng):
- Quy trình A nhận được yêu cầu tạo người dùng mới với tên 'foo'
- Quy trình B làm điều tương tự
- Quy trình A xác nhận tính duy nhất của 'foo' bằng cách hỏi DB xem tên đó có tồn tại hay không và DB cho biết tên đó chưa tồn tại.
- Quy trình B làm điều tương tự và nhận được phản hồi tương tự
- Quy trình A gửi
insert
tuyên bố cho bản ghi mới và thành công
- Nếu bạn có ràng buộc cơ sở dữ liệu yêu cầu tính duy nhất cho trường đó, Quy trình B sẽ gửi
insert
câu lệnh cho bản ghi mới và không thành công với một ngoại lệ máy chủ xấu xí quay lại từ bộ điều hợp SQL. Nếu bạn không có ràng buộc cơ sở dữ liệu, việc chèn sẽ thành công và bây giờ bạn có hai hàng với tên 'foo'.
Xem thêm "Đồng thời và tính toàn vẹn" trong validates_uniqueness_of
tài liệu Rails.
Từ Ruby on Rails phiên bản thứ 3 :
... mặc dù tên của nó, validates_uniqueness_of không thực sự đảm bảo rằng các giá trị cột sẽ là duy nhất. Tất cả những gì nó có thể làm là xác minh rằng không có cột nào có cùng giá trị với giá trị trong bản ghi đang được xác thực tại thời điểm xác thực được thực hiện. Có thể tạo hai bản ghi cùng một lúc, mỗi bản ghi có cùng giá trị cho một cột phải là duy nhất và để cả hai bản ghi vượt qua xác thực. Cách đáng tin cậy nhất để thực thi tính duy nhất là sử dụng ràng buộc cấp cơ sở dữ liệu. "
Xem thêm kinh nghiệm của lập trình viên này với validates_uniqueness_of
.
Một cách mà điều này thường xảy ra là tình cờ gửi hai lần từ một trang web khi tạo tài khoản mới. Đây là một vấn đề khó giải quyết vì những gì người dùng sẽ nhận lại là lỗi thứ hai (xấu xí) và nó sẽ khiến họ nghĩ rằng đăng ký của họ không thành công, trong khi thực tế nó đã thành công. Cách tốt nhất mà tôi đã tìm ra để ngăn chặn điều này là sử dụng javascript để cố gắng ngăn việc gửi hai lần.