अद्वितीय अनुक्रमणिका और validates_uniqueness_of
. के बीच अंतर यहां दिए गए हैंयह एक पैच है जो ActiveRecord को अद्वितीय बाधा उल्लंघनों के लिए डीबी-जनरेटेड त्रुटियों की पहचान करने में सक्षम बनाता है। उदाहरण के लिए, यह एकValids_uniqueness_of घोषित किए बिना निम्नलिखित कार्य करता है:
create_table "users" do |t|
t.string "email", null: false
end
add_index "users", ["email"], unique: true
class User < ActiveRecord::Base
end
User.create!(email: '[email protected]')
u = User.create(email: '[email protected]')
u.errors[:email]
=> "has already been taken"
लाभ हैं गति, उपयोग में आसानी, और पूर्णता --
गति
इस दृष्टिकोण के साथ आपको बचत करते समय विशिष्टता की जांच करने के लिए डीबी लुकअप करने की आवश्यकता नहीं है (जो कभी-कभी इंडेक्स छूटने पर काफी धीमा हो सकता है - https://rails.lighthouseapp.com/projects/8994/tickets/2503-validate.. . ) यदि आप वास्तव में विशिष्टता को मान्य करने की परवाह करते हैं तो आपको डेटाबेस बाधाओं का उपयोग करना होगा, इसलिए डेटाबेस विशिष्टता को मान्य करेगा इससे कोई फर्क नहीं पड़ता कि यह दृष्टिकोण अतिरिक्त क्वेरी को हटा देता है। इंडेक्स को दो बार जांचना डीबी के लिए कोई समस्या नहीं है (इसे दूसरी बार कैश किया गया है), लेकिन एप्लिकेशन से डीबी राउंड-ट्रिप को सहेजना एक बड़ी जीत है।
उपयोग में आसानी
यह देखते हुए कि आपके पास वैसे भी सच्ची विशिष्टता के लिए डीबी बाधाएं होनी चाहिए, डीबी बाधाओं के होने के बाद यह दृष्टिकोण सब कुछ स्वचालित रूप से होने देगा। यदि आप चाहें तो आप अभी भीValids_uniqueness_of का उपयोग कर सकते हैं।
पूर्णता
Valids_uniqueness_of हमेशा एक हैक का एक सा रहा है - यह दौड़ की स्थिति को ठीक से संभाल नहीं सकता है और इसके परिणामस्वरूप अपवादों को कुछ हद तक अनावश्यक त्रुटि प्रबंधन तर्क का उपयोग करके नियंत्रित किया जाना चाहिए। (http://api.rubyonrails में "कंकरेंसी एंड इंटीग्रिटी" सेक्शन देखें। .org/classes/ActiveRecord/Validations/ClassMe... )
मान्यता_की_अनन्यता एक मूल्य की विशिष्टता सुनिश्चित करने के लिए पर्याप्त नहीं है। इसका कारण यह है कि उत्पादन में, कई कार्यकर्ता प्रक्रियाएं दौड़ की स्थिति पैदा कर सकती हैं:
-
दो समवर्ती अनुरोध एक ही नाम के साथ एक उपयोगकर्ता बनाने का प्रयास करते हैं (और हम चाहते हैं कि उपयोगकर्ता नाम अद्वितीय हों)
-
सर्वर पर दो कार्यकर्ता प्रक्रियाओं द्वारा अनुरोध स्वीकार किए जाते हैं जो अब उन्हें समानांतर में संसाधित करेंगे
-
दोनों अनुरोध उपयोगकर्ता तालिका को स्कैन करते हैं और देखते हैं कि नाम उपलब्ध है
-
दोनों अनुरोध सत्यापन पास करते हैं और प्रतीत होता है उपलब्ध नाम के साथ एक उपयोगकर्ता बनाते हैं
अधिक स्पष्ट समझ के लिए कृपया इसे जांचें
यदि आप किसी स्तंभ के लिए एक अद्वितीय अनुक्रमणिका बनाते हैं, तो इसका मतलब है कि आप इस बात की गारंटी देते हैं कि तालिका में उस स्तंभ के लिए समान मान वाली एक से अधिक पंक्तियाँ नहीं होंगी। अपने मॉडल में केवलValids_uniqueness_of सत्यापन का उपयोग करना विशिष्टता को लागू करने के लिए पर्याप्त नहीं है क्योंकि समवर्ती उपयोगकर्ता समान डेटा बनाने का प्रयास कर सकते हैं।
कल्पना करें कि दो उपयोगकर्ता एक ही ईमेल के साथ एक खाता पंजीकृत करने का प्रयास करते हैं जहां आपने अपने उपयोगकर्ता मॉडल मेंValids_uniqueness_of :email जोड़ा है। यदि वे एक ही समय में "साइन अप" बटन दबाते हैं, तो रेल उस ईमेल के लिए उपयोगकर्ता तालिका में देखेंगे और जवाब देंगे कि सब कुछ ठीक है और तालिका में रिकॉर्ड को सहेजना ठीक है। रेल फिर एक ही ईमेल के साथ दो रिकॉर्ड उपयोगकर्ता तालिका में सहेजेंगे और अब आपके पास निपटने के लिए वास्तव में एक छोटी सी समस्या है।
इससे बचने के लिए आपको डेटाबेस स्तर पर भी एक अद्वितीय बाधा बनाने की आवश्यकता है:
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :email
...
end
add_index :users, :email, unique: true
end
end
तो index_users_on_email अद्वितीय अनुक्रमणिका बनाकर आपको दो बहुत अच्छे लाभ मिलते हैं। डेटा अखंडता और अच्छा प्रदर्शन क्योंकि अद्वितीय अनुक्रमणिका बहुत तेज़ होती हैं।
यदि आप user_id के लिए अपनी पोस्ट तालिका में unique:true डालते हैं तो यह समान user_id के साथ डुप्लिकेट रिकॉर्ड दर्ज करने की अनुमति नहीं देगा।