Rails“ validates_uniqueness_of” Case Sensitivity


96

นี่คือโมเดล (ฉันใช้ SQLLite3):

class School < ActiveRecord::Base

  validates_uniqueness_of :name

end

ตัวอย่างเช่นหลังจากฉันเพิ่ม "เยล" ฉันไม่สามารถเพิ่ม "เยล" แต่สามารถเพิ่ม "เยล" ได้ ฉันจะทำให้กรณีการตรวจสอบความถูกต้องไม่สำคัญได้อย่างไร

แก้ไข: พบแล้ว - การตรวจสอบระเบียนที่ใช้งานอยู่

คำตอบ:


232

validates_uniqueness_of :name, :case_sensitive => falseไม่หลอกลวง แต่คุณควรเก็บไว้ในใจว่าvalidates_uniqueness_ofจะไม่ได้รับประกันไม่ซ้ำกันถ้าคุณมีเซิร์ฟเวอร์หลาย / กระบวนการเซิร์ฟเวอร์ (เช่นทำงาน Phusion ผู้โดยสารหลาย Mongrels ฯลฯ ) หรือเซิร์ฟเวอร์แบบมัลติเธรด นั่นเป็นเพราะคุณอาจได้รับลำดับของเหตุการณ์นี้ (ลำดับมีความสำคัญ):

  1. กระบวนการ A ได้รับการร้องขอให้สร้างผู้ใช้ใหม่ด้วยชื่อ 'foo'
  2. กระบวนการ B ทำสิ่งเดียวกัน
  3. กระบวนการ A ตรวจสอบความเป็นเอกลักษณ์ของ 'foo' โดยถาม DB ว่ายังมีชื่อนั้นอยู่หรือไม่และ DB บอกว่ายังไม่มีชื่อ
  4. กระบวนการ B ทำสิ่งเดียวกันและได้รับการตอบสนองเดียวกัน
  5. กระบวนการ A ส่งinsertคำสั่งสำหรับบันทึกใหม่และประสบความสำเร็จ
  6. ถ้าคุณมีข้อ จำกัด ของฐานข้อมูลที่ต้องการความไม่ซ้ำกันสำหรับฟิลด์นั้นกระบวนการ B จะส่งinsertคำสั่งสำหรับเร็กคอร์ดใหม่และล้มเหลวด้วยข้อยกเว้นเซิร์ฟเวอร์ที่น่าเกลียดซึ่งกลับมาจากอะแด็ปเตอร์ SQL หากคุณไม่มีข้อ จำกัด ของฐานข้อมูลการแทรกจะสำเร็จและตอนนี้คุณมีสองแถวที่มี 'foo' เป็นชื่อ

โปรดดู "ความพร้อมกันและความสมบูรณ์" ในvalidates_uniqueness_ofเอกสาร Rails

จากRuby on Rails 3rd Edition :

... แม้จะมีชื่อ แต่ validates_uniqueness_of ก็ไม่รับประกันว่าค่าคอลัมน์จะไม่ซ้ำกัน สิ่งที่ทำได้คือตรวจสอบว่าไม่มีคอลัมน์ใดที่มีค่าเหมือนกับในเรกคอร์ดที่กำลังตรวจสอบความถูกต้องในขณะที่ทำการตรวจสอบความถูกต้อง เป็นไปได้ที่จะสร้างสองระเบียนพร้อมกันโดยแต่ละระเบียนจะมีค่าเดียวกันสำหรับคอลัมน์ที่ควรไม่ซ้ำกันและเพื่อให้ทั้งสองระเบียนผ่านการตรวจสอบความถูกต้อง วิธีที่น่าเชื่อถือที่สุดในการบังคับใช้ความเป็นเอกลักษณ์คือข้อ จำกัด ระดับฐานข้อมูล "

ดูเพิ่มเติมประสบการณ์ของโปรแกรมเมอร์นี้validates_uniqueness_ofด้วย

วิธีหนึ่งที่มักเกิดขึ้นคือการส่งข้อมูลซ้ำสองครั้งจากหน้าเว็บเมื่อสร้างบัญชีใหม่ นี่เป็นวิธีแก้ไขที่ยากเพราะสิ่งที่ผู้ใช้จะได้รับกลับมาคือข้อผิดพลาดที่สอง (น่าเกลียด) และจะทำให้พวกเขาคิดว่าการลงทะเบียนล้มเหลวเมื่อในความเป็นจริงมันประสบความสำเร็จ วิธีที่ดีที่สุดที่ฉันพบเพื่อป้องกันปัญหานี้คือใช้จาวาสคริปต์เพื่อพยายามป้องกันการส่งซ้ำ


4
หมายเหตุ - นี่คือแพตช์ที่ฉันส่งไปยัง Rails เพื่อพยายามแก้ไขปัญหานี้โดยใช้ข้อ จำกัด ระดับฐานข้อมูล: rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/…
Jordan Brough

นอกจากนี้ยังมีปัญหา "ผู้ใช้คลิกสองครั้งที่ปุ่มส่ง" ตลอดกาล แต่นั่นเป็นการแก้ไขมากกว่าโดยใช้: disable_with
Ghoti

79

ในราง 3 คุณสามารถทำได้ในแบบจำลองของคุณ:

validates :name, :uniqueness => true

หรือไม่มี case_sensitivity

validates :name, :uniqueness => {:case_sensitive => false}

นี่คือสิ่งที่ฉันต้องการ
Jigar Bhatt

2
ฉันทำ Rails มานานกว่า 10 ปี ฉันไม่อยากจะเชื่อเลยว่าฉันเพิ่งเรียนรู้เกี่ยวกับตัวเลือกนี้ ใน Rails มีอะไรใหม่ ๆ ให้เรียนรู้อยู่เสมอ ... ไม่ว่าจะเป็นระดับทักษะใดก็ตาม
danielricecodes

25

มีตัวเลือกที่คุณสามารถระบุตัวพิมพ์เล็กและใหญ่

  validates_uniqueness_of :name, :case_sensitive => false

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.