validates_uniqueness_of :name, :case_sensitive => false
ไม่หลอกลวง แต่คุณควรเก็บไว้ในใจว่าvalidates_uniqueness_of
จะไม่ได้รับประกันไม่ซ้ำกันถ้าคุณมีเซิร์ฟเวอร์หลาย / กระบวนการเซิร์ฟเวอร์ (เช่นทำงาน Phusion ผู้โดยสารหลาย Mongrels ฯลฯ ) หรือเซิร์ฟเวอร์แบบมัลติเธรด นั่นเป็นเพราะคุณอาจได้รับลำดับของเหตุการณ์นี้ (ลำดับมีความสำคัญ):
- กระบวนการ A ได้รับการร้องขอให้สร้างผู้ใช้ใหม่ด้วยชื่อ 'foo'
- กระบวนการ B ทำสิ่งเดียวกัน
- กระบวนการ A ตรวจสอบความเป็นเอกลักษณ์ของ 'foo' โดยถาม DB ว่ายังมีชื่อนั้นอยู่หรือไม่และ DB บอกว่ายังไม่มีชื่อ
- กระบวนการ B ทำสิ่งเดียวกันและได้รับการตอบสนองเดียวกัน
- กระบวนการ A ส่ง
insert
คำสั่งสำหรับบันทึกใหม่และประสบความสำเร็จ
- ถ้าคุณมีข้อ จำกัด ของฐานข้อมูลที่ต้องการความไม่ซ้ำกันสำหรับฟิลด์นั้นกระบวนการ B จะส่ง
insert
คำสั่งสำหรับเร็กคอร์ดใหม่และล้มเหลวด้วยข้อยกเว้นเซิร์ฟเวอร์ที่น่าเกลียดซึ่งกลับมาจากอะแด็ปเตอร์ SQL หากคุณไม่มีข้อ จำกัด ของฐานข้อมูลการแทรกจะสำเร็จและตอนนี้คุณมีสองแถวที่มี 'foo' เป็นชื่อ
โปรดดู "ความพร้อมกันและความสมบูรณ์" ในvalidates_uniqueness_of
เอกสาร Rails
จากRuby on Rails 3rd Edition :
... แม้จะมีชื่อ แต่ validates_uniqueness_of ก็ไม่รับประกันว่าค่าคอลัมน์จะไม่ซ้ำกัน สิ่งที่ทำได้คือตรวจสอบว่าไม่มีคอลัมน์ใดที่มีค่าเหมือนกับในเรกคอร์ดที่กำลังตรวจสอบความถูกต้องในขณะที่ทำการตรวจสอบความถูกต้อง เป็นไปได้ที่จะสร้างสองระเบียนพร้อมกันโดยแต่ละระเบียนจะมีค่าเดียวกันสำหรับคอลัมน์ที่ควรไม่ซ้ำกันและเพื่อให้ทั้งสองระเบียนผ่านการตรวจสอบความถูกต้อง วิธีที่น่าเชื่อถือที่สุดในการบังคับใช้ความเป็นเอกลักษณ์คือข้อ จำกัด ระดับฐานข้อมูล "
ดูเพิ่มเติมประสบการณ์ของโปรแกรมเมอร์นี้validates_uniqueness_of
ด้วย
วิธีหนึ่งที่มักเกิดขึ้นคือการส่งข้อมูลซ้ำสองครั้งจากหน้าเว็บเมื่อสร้างบัญชีใหม่ นี่เป็นวิธีแก้ไขที่ยากเพราะสิ่งที่ผู้ใช้จะได้รับกลับมาคือข้อผิดพลาดที่สอง (น่าเกลียด) และจะทำให้พวกเขาคิดว่าการลงทะเบียนล้มเหลวเมื่อในความเป็นจริงมันประสบความสำเร็จ วิธีที่ดีที่สุดที่ฉันพบเพื่อป้องกันปัญหานี้คือใช้จาวาสคริปต์เพื่อพยายามป้องกันการส่งซ้ำ