कई स्तंभों की अद्वितीयता को मान्य करें


193

क्या मान्य करने के लिए रेल-रास्ता है कि एक वास्तविक रिकॉर्ड अद्वितीय है और सिर्फ एक स्तंभ नहीं है? उदाहरण के लिए, एक दोस्ती मॉडल / तालिका में कई समान रिकॉर्ड नहीं होने चाहिए, जैसे:

user_id: 10 | friend_id: 20
user_id: 10 | friend_id: 20

7
मुझे माफ कर दो अगर मैं सघन हो रहा हूं, लेकिन इस स्थिति में कैसे मदद मिलेगी?
5

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

1
@HarryJoy, उन्होंने पूछा Is there a rails-way way। और आप उसे गैर-रेल मार्ग की पेशकश करते हैं, लेकिन मानक। The Active Record way claims that intelligence belongs in your models, not in the database.
ग्रीन

2
दुर्भाग्य validates :field_name, unique: trueसे दौड़ की स्थिति होने का खतरा है, भले ही रेल-रास्ते के खिलाफ, एक वास्तविक बाधा को प्राथमिकता दी जाती है। @HarryJoy मैं बाधा पैदा करने वाले तरीके का वर्णन करता हूं।
पूयन खोसरावी

1
बेहतर जवाब तो नीचे दिए गए सभी उल्लेख है यह एक stackoverflow.com/a/34425284/1612469 है क्योंकि यह सुनिश्चित करने के लिए एक और परत लाता है कि सब कुछ सही ढंग से काम करेगा
Aleks

जवाबों:


319

आप validates_uniqueness_ofनिम्नानुसार कॉल को स्कोप कर सकते हैं।

validates_uniqueness_of :user_id, :scope => :friend_id

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

27
अजीब जो आप नहीं कह सकते validates_uniqueness_of [:user_id, :friend_id]। शायद यह पैच करने की आवश्यकता है?
अलेक्सी

12
एलेक्सी, validates_uniqueness_of [: user_id,: friend_id] सूचीबद्ध क्षेत्रों में से प्रत्येक के लिए सत्यापन करेंगे - और यह प्रलेखित और अपेक्षित व्यवहार है
निकिता हिसमातोव

71
रेल 4 में, यह हो जाता है: मान्य: user_id, विशिष्टता: {गुंजाइश:: friend_id}
मरीना मार्टिन

3
आप शायद एक कस्टम त्रुटि संदेश जोड़ना चाहते हैं जैसे: संदेश => 'पहले से ही यह मित्र है।'
laffuste

137

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

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

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

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

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

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

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

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

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

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

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

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

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

2

यह दो स्तंभों पर एक डेटाबेस बाधा के साथ किया जा सकता है:

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

आप एक रेल सत्यापनकर्ता का उपयोग कर सकते हैं, लेकिन सामान्य तौर पर मैं एक डेटाबेस बाधा का उपयोग करने की सलाह देता हूं।

अधिक पढ़ने: https://robots.thoughtbot.com/validation-database-constraint-or-both

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.