178

क्या यह सत्यापित करने के लिए एक रेलवे तरीका है कि एक वास्तविक रिकॉर्ड अद्वितीय है और केवल एक कॉलम नहीं है?एकाधिक कॉलम की विशिष्टता को मान्य करें

user_id: 10 | friend_id: 20 
user_id: 10 | friend_id: 20 
+7

मुझे माफ़ कर दो अगर मैं घना हो रहा हूं, लेकिन यह इस स्थिति में कैसे मदद करेगा? – re5et

+2

अपने मॉडल में "validates_uniqueness_of" का उपयोग करने का प्रयास करें। यदि यह एक इंडेक्स बनाने की कोशिश नहीं करता है जिस पर आप फील्ड का माइग्रेशन बना सकते हैं जिसमें add_index: table, [: column_a,: column_b],: unique => true) –

+1

@ हैरीजॉय ने पूछा, क्या रेलवे रास्ता है '। और आप उसे गैर-रेल मार्ग प्रदान करते हैं, लेकिन मानक। 'सक्रिय रिकॉर्ड तरीका का दावा है कि खुफिया डेटाबेस में नहीं, आपके मॉडल में है। – Green

उत्तर

306

आप गुंजाइश कर सकते हैं एक validates_uniqueness_of कॉल इस प्रकार है: उदाहरण के लिए, एक दोस्ती मॉडल/तालिका की तरह अनेक एक रिकॉर्ड करने में सक्षम नहीं होना चाहिए।

validates_uniqueness_of :user_id, :scope => :friend_id 
+78

बस यह जोड़ना चाहता था कि आप मामले में एकाधिक स्कोप पैरा आपको 2 से अधिक फ़ील्ड पर विशिष्टता को सत्यापित करने की आवश्यकता है। अर्थात। : स्कोप => [: friend_id,: group_id] –

+25

अजीब है कि आप 'validates_uniqueness_of [: user_id,: friend_id]' नहीं कह सकते हैं। शायद इसे पैच किया जाना चाहिए? – Alexey

+11

Alexey, validates_uniqueness_of [: user_id,: friend_id] केवल सूचीबद्ध फ़ील्ड के लिए सत्यापन करेगा - और यह दस्तावेज और अपेक्षित व्यवहार –

32

आपको शायद डीबी पर वास्तविक बाधाओं की आवश्यकता है, क्योंकि वैधता दौड़ की स्थिति से पीड़ित है।

validates_uniqueness_of :user_id, :scope => :friend_id 

जब आप किसी उपयोगकर्ता उदाहरण जारी रहती है, रेल एक चयन करें क्वेरी चल रहा है, तो किसी भी उपयोगकर्ता रिकॉर्ड पहले से प्रदान की user_id के साथ मौजूद हैं देखने के लिए अपने मॉडल को मान्य होगा। रिकॉर्ड मानते हुए वैध साबित होता है, रेल उपयोगकर्ता को जारी रखने के लिए INSERT कथन चलाएंगे। यदि आप एकल प्रक्रिया/थ्रेड वेब सर्वर का एक उदाहरण चला रहे हैं तो यह बहुत अच्छा काम करता है।

यदि दो प्रक्रियाएं/थ्रेड एक ही उपयोगकर्ता के साथ एक ही उपयोगकर्ता_आईडी के साथ उपयोगकर्ता बनाने की कोशिश कर रहे हैं, तो निम्न स्थिति उत्पन्न हो सकती है। Race condition with validates

डीबी पर अद्वितीय इंडेक्स के साथ, उपरोक्त स्थिति निम्नानुसार खेल जाएगी। Unique indexes on db

उत्तर इस ब्लॉग पोस्ट से लिया - http://robots.thoughtbot.com/the-perils-of-uniqueness-validations

+3

मान्य करने का प्रयास करें और रेलवे माइग्रेशन सिस्टम के साथ हम डीबी-साइड बाधाओं (एकाधिक कॉलम के बीच अद्वितीय संयम) कैसे प्राप्त कर सकते हैं? –

+0

http://stackoverflow.com/questions/4123610/how-to-implement-a-unique-index-on-two-columns-in-rails –

+0

@LeeHanKyeol ऐसा करने के लिए आप डीफ़ चेंज add_index जैसे कुछ कर सकते हैं : उपयोगकर्ता, ईमेल, अनन्य: सत्य अंत अंत –

113

आप validates उपयोग कर सकते हैं एक स्तंभ पर uniqueness मान्य करने के लिए:

validates :user_id, uniqueness: {scope: :friend_id} 

एकाधिक स्तंभों पर सत्यापन के लिए वाक्य रचना समान है, लेकिन आपको चाहिए इसके बजाय फ़ील्ड की एक सरणी प्रदान करें:

validates :attr, uniqueness: {scope: [:attr1, ... , :attrn]} 

हालांकि, ऊपर दिखाए गए सत्यापन दृष्टिकोण में दौड़ की स्थिति है और स्थिरता सुनिश्चित नहीं कर सकता है। निम्न उदाहरण पर विचार करें:

  1. डेटाबेस तालिका रिकॉर्ड n क्षेत्रों से अद्वितीय होना चाहिए रहे हैं;

  2. कई (दो या अधिक) समवर्ती अनुरोधों, अलग प्रक्रियाओं को एक (आवेदन सर्वर, पृष्ठभूमि कार्यकर्ता सर्वर या जो भी आप उपयोग कर रहे हैं), पहुँच डेटाबेस द्वारा नियंत्रित तालिका में एक ही रिकॉर्ड सम्मिलित करने के लिए;

  3. समानांतर में प्रत्येक प्रक्रिया समान एन फ़ील्ड के साथ रिकॉर्ड होने पर समान प्रक्रिया में मान्य होती है;

  4. प्रत्येक अनुरोध के लिए सत्यापन सफलतापूर्वक पारित किया गया है, और प्रत्येक प्रक्रिया तालिका में एक ही डेटा के साथ एक रिकॉर्ड बनाता है।

इस तरह का व्यवहार न हो, इसके एक तालिका db से एक अद्वितीय बाधा जोड़ना चाहिए।

class AddUniqueConstraints < ActiveRecord::Migration 
    def change 
    add_index :table_name, [:field1, ... , :fieldn], unique: true 
    end 
end 

चेतावनी:: आप निम्न माइग्रेशन चलाकर एक (या एकाधिक) क्षेत्र (रों) के लिए add_index सहायक के साथ सेट कर सकते हैं आप एक अद्वितीय बाधा निर्धारित करने के बाद भी, दो या अधिक समवर्ती अनुरोध करेंगे db से एक ही डेटा लिखने की कोशिश, लेकिन इसके बजाय डुप्लिकेट रिकॉर्ड बनाने के बजाय, यह एक ActiveRecord::RecordNotUnique अपवाद है, जो आप अलग से संभाल चाहिए बढ़ा देंगे:

begin 
# writing to database 
rescue ActiveRecord::RecordNotUnique => e 
# handling the case when record already exists 
end 
+1

सुनिश्चित करने के लिए डुप्लिकेट को रोकने के लिए डेटाबेस-स्तर यूनिक इंडेक्स है धन्यवाद श्रीमान !! – nuc

0

डीबी बाधा:

add_index :friendships, [:user_id, :friend_id], unique: true

संबंधित मुद्दे