बिना अपवाद के ऐरे रेल्स एक्टिवरीकार्ड में आईडी का चयन कैसे करें


135

जब मेरे पास id की तरह है, जैसे

ids = [2,3,5]

और मैं प्रदर्शन करता हूं

Comment.find(ids)

सब कुछ ठीक काम करता है। लेकिन जब कोई ऐसी आईडी होती है जो मौजूद नहीं होती है, तो मुझे एक अपवाद मिलता है। यह सामान्य तब होता है जब मुझे कुछ फ़िल्टर से मेल खाने वाली आईडी की सूची मिलती है और जैसे मैं कुछ करता हूं

current_user.comments.find(ids)

इस बार मेरे पास एक मान्य टिप्पणी आईडी हो सकती है, जो हालांकि दिए गए उपयोगकर्ता की नहीं है, इसलिए यह नहीं मिली है और मुझे इसका अपवाद नहीं मिला है।

मैंने कोशिश की है find(:all, ids), लेकिन यह सारे रिकॉर्ड लौटाता है।

एकमात्र तरीका यह कर सकता हूं कि वह अब है

current_user.comments.select { |c| ids.include?(c.id) }

लेकिन यह मुझे सुपर अकुशल समाधान की तरह लगता है।

क्या गैर-मौजूदा रिकॉर्ड पर अपवाद प्राप्त किए बिना ऐरे में आईडी का चयन करने का बेहतर तरीका है ?

जवाबों:


216

यदि यह केवल उस अपवाद से बच रहा है जिसके बारे में आप चिंतित हैं, तो "find_all_by .." फ़ंक्शन के परिवार अपवादों को फेंकने के बिना काम करते हैं।

Comment.find_all_by_id([2, 3, 5])

अगर कुछ आईडी मौजूद नहीं हैं तो भी काम करेगा। इस में काम करता है

user.comments.find_all_by_id(potentially_nonexistent_ids)

मामला भी।

अपडेट: रेल्स 4

Comment.where(id: [2, 3, 5])

यह मेरा पसंदीदा समाधान है, यह अपवाद हैंडलिंग मार्ग की तुलना में साफ-सुथरा लगता है
सैम सैफ्रन

5
इसके लिए एक और विस्तार के रूप में, आपको जटिल परिस्थितियों को श्रृंखलाबद्ध करने की आवश्यकता है, आप टिप्पणी भी कर सकते हैं। (: शर्तें => ["स्वीकृत और आईडी इन (?)", [1,2,3]])
उमर कुरैशी

14
यह रेल 4 में पदावनत किया जाएगा: edgeguides.rubyonrails.org/…
जोनाथन लिन

3
@JonathanLin सही है, mjnissim के उत्तर को प्राथमिकता दी जानी चाहिए: stackoverflow.com/a/11457025/33226
गैविन मिलर

6
यह एक के Arrayबजाय रिटर्न करता है ActiveRecord::Relation, जो आपको बाद में इसके साथ क्या कर सकता है, इसे सीमित करता है। Comment.where(id: [2, 3, 5])एक वापसी है ActiveRecord::Relation
जोशुआ पिंटर

148

अद्यतन: यह उत्तर रेल 4.x के लिए अधिक प्रासंगिक है

यह करो:

current_user.comments.where(:id=>[123,"456","Michael Jackson"])

इस दृष्टिकोण का मजबूत पक्ष यह है कि यह एक Relationवस्तु लौटाता है , जिसमें आप अधिक .whereखंडों, .limitखंडों इत्यादि में शामिल हो सकते हैं , जो बहुत सहायक है। यह अपवादों को फेंकने के बिना गैर-मौजूद आईडी की भी अनुमति देता है।

नया रूबी सिंटैक्स होगा:

current_user.comments.where(id: [123, "456", "Michael Jackson"])

whereसरणी की तुलना करते समय वाक्यविन्यास की पुष्टि करने के लिए धन्यवाद । मुझे लगा कि मुझे एसक्यूएल को एक INबयान के साथ कोड करना पड़ सकता है , लेकिन यह क्लीनर दिखता है और पदावनत के लिए एक आसान प्रतिस्थापन है scoped_by_id
मार्क बेरी

1
इसे क्या कहा जाता है और यह कैसे काम करता है? क्या यह जादू है? एक सहयोगी ने टिप्पणी के रूप में, अपने तरह 'एक वस्तु सूची "के साथ एक पूर्णांक की तुलना।
ATW

23

यदि आपको अधिक नियंत्रण की आवश्यकता है (शायद आपको तालिका नाम बताने की आवश्यकता है) तो आप निम्न कार्य भी कर सकते हैं:

Model.joins(:another_model_table_name)
  .where('another_model_table_name.id IN (?)', your_id_array)

ठीक वही जो मेरे द्वारा खोजा जा रहा था। धन्यवाद!
Myxtic

क्या your_id_arrayवस्तुओं को वापस पाने के क्रम को बनाए रखने का कोई तरीका है ?
जोशुआ पिंटर

@JoshPinter मुझे नहीं लगता कि यह डेटाबेस को उसी क्रम में चीजों को वापस करने की उम्मीद करने का एक विश्वसनीय तरीका है। शायद चीजों के सही क्रम को सुनिश्चित करने के लिए अंत में एक ORDER BY क्वेरी जोड़ें।
जोनाथन लिन

जोनाथन प्रतिक्रिया के लिए @JonathanLin धन्यवाद। आप निश्चित रूप से सही हैं। उपयोग करना ORDER BYमेरी स्थिति में काम नहीं करेगा क्योंकि आदेश एक विशेषता पर आधारित नहीं है। हालाँकि, इसे SQL के माध्यम से करने का एक तरीका है (इसलिए यह तेज़ है) और किसी ने इसके लिए एक मणि भी बनाया है। इस प्रश्नोत्तर की जाँच करें: stackoverflow.com/questions/801824/…
जोशुआ पिंटर

10

अब .find और .find_by_id तरीकों को रेल में हटा दिया गया है 4. इसलिए इसके बजाय हम नीचे उपयोग कर सकते हैं:

Comment.where(id: [2, 3, 5])

अगर कुछ आईडी मौजूद नहीं हैं तो भी यह काम करेगा। इस में काम करता है

user.comments.where(id: avoided_ids_array)

आईडी को छोड़कर

Comment.where.not(id: [2, 3, 5])

3
github.com/rails/activerecord-deprecated_fenders .find और .find_by_id विधियाँ रेल में नहीं निकाली गई हैं 4.
Canna

0

अपने ऐप को मारने वाले अपवादों से बचने के लिए आपको उन अपवादों को पकड़ना चाहिए और उन्हें अपनी इच्छानुसार व्यवहार करना चाहिए, आपके लिए व्यवहार को परिभाषित करते हुए उन स्थितियों पर ऐप करना चाहिए जहाँ आईडी नहीं मिली है।

begin
  current_user.comments.find(ids)
rescue
  #do something in case of exception found
end

यहाँ माणिक में अपवादों के बारे में अधिक जानकारी है


1
इस समस्या को हल करता है, लेकिन यह वास्तव में एक साफ समाधान नहीं है
याकूब अर्नोल्ड

3
यदि आप एक अपवाद को पकड़ने जा रहे हैं, तो आपको उस अपवाद को घोषित करना चाहिए जिसे आप पकड़ने की अपेक्षा करते हैं, अन्यथा आप इसे जोखिम में डालते हैं कुछ ऐसा जिसे आप उम्मीद नहीं कर रहे थे और एक वास्तविक समस्या को छिपा रहे थे।
हैगिन

0

यदि आप अन्य शर्तों को रखना चाहते हैं, तो आप इसका नाम name_scope में भी उपयोग कर सकते हैं

उदाहरण के लिए कुछ अन्य मॉडल शामिल हैं:

name_scope 'get_by_ids', lambda {| आईडी | {= शामिल करें => [: टिप्पणियाँ], स्थितियां => ["टिप्पणियाँ .id IN (?)", आईडी]}}

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