validates_uniqueness_of :name, :case_sensitive => false
hile yapar, ancak birden fazla sunucunuz / sunucu işleminiz (örneğin Phusion Passenger çalıştıran, birden çok Mongrels, vb.) veya çok iş parçacıklı bir sunucunuz varsa validates_uniqueness_of
, bunun benzersizliği garanti etmediğini aklınızda bulundurmalısınız . Bunun nedeni, şu olaylar dizisini alabilmenizdir (sıra önemlidir):
- İşlem A, 'foo' adında yeni bir kullanıcı oluşturma isteği alır
- Süreç B aynı şeyi yapar
- İşlem A, DB'ye bu adın henüz mevcut olup olmadığını ve DB'nin adın henüz mevcut olmadığını söyleyerek 'foo'nun benzersizliğini doğrular.
- Süreç B aynı şeyi yapıyor ve aynı yanıtı alıyor
- İşlem A
insert
, yeni kayıt için ifadeyi gönderir ve başarılı olur
- Bu alan için benzersizlik gerektiren bir veritabanı kısıtlamanız varsa, İşlem B
insert
yeni kayıt için ifadeyi gönderir ve SQL adaptöründen gelen çirkin bir sunucu istisnasıyla başarısız olur . Bir veritabanı kısıtlamanız yoksa, ekleme başarılı olur ve artık ad olarak 'foo' olan iki satırınız olur.
Ayrıca validates_uniqueness_of
Rails belgelerinde "Eşzamanlılık ve bütünlük" konusuna bakın .
Gönderen Raylar 3rd Edition Ruby :
... ismine rağmen, validates_uniqueness_of sütun değerlerinin benzersiz olacağını garanti etmez. Yapabileceği tek şey, hiçbir sütunun, doğrulama gerçekleştirildiği sırada doğrulanmakta olan kayıttaki değerle aynı değere sahip olmadığını doğrulamaktır. Her biri benzersiz olması gereken bir sütun için aynı değere ve her iki kaydın da doğrulamayı geçmesi için aynı anda iki kaydın oluşturulması mümkündür. Benzersizliği sağlamanın en güvenilir yolu, veritabanı düzeyinde kısıtlamadır. "
Ayrıca bkz Bu programcının deneyimi ile validates_uniqueness_of
.
Bunun yaygın olarak meydana gelmesinin bir yolu, yeni bir hesap oluştururken bir web sayfasından yanlışlıkla çift gönderim yapılmasıdır. Bu çözülmesi zor bir sorundur çünkü kullanıcının geri alacağı şey ikinci (çirkin) hatadır ve gerçekte başarılı olduğunda kayıtlarının başarısız olduğunu düşünmelerini sağlar. Bunu önlemek için bulduğum en iyi yol, yalnızca javascript kullanarak çift gönderimi engellemeye çalışmaktır.