Rails में, यदि आपके पास उनकी आईडी हैं तो अपने डेटाबेस से रिकॉर्ड्स का एक गुच्छा प्राप्त करना आसान है:
Person.where(id: [1, 2, 3]).map(&:id) => [1, 2, 3]pre>लेकिन क्या होगा यदि आप रिकॉर्ड्स को अलग क्रम में वापस प्राप्त करना चाहते हैं? शायद आपका सर्च इंजन सबसे प्रासंगिक आईडी पहले लौटाता है। आप अपने रिकॉर्ड्स को उस क्रम में कैसे रखते हैं?
आप फिर से
whereआज़मा सकते हैं:Person.where(id: [2, 1, 3]).map(&:id) => [1, 2, 3]pre>लेकिन यह बिल्कुल भी काम नहीं करता। तो आप अपने रिकॉर्ड्स को सही क्रम में कैसे प्राप्त करते हैं?
संगत तरीका:
caseस्टेटमेंट्सरूबी की तरह, SQL
case...whenस्टेटमेंट्स का समर्थन करता है।आप इसे बहुत बार नहीं देखते, लेकिन
case...whenस्टेटमेंट्स लगभग हैश की तरह कार्य कर सकते हैं। आप एक मान को दूसरे पर मैप कर सकते हैं:case :b when :a then 1 when :b then 2 when :c then 3 end # => 2pre>वह केस स्टेटमेंट एक हैश की तरह दिखता है:
{ :a => 1, :b => 2, :c => 3 }[:b] # => 2pre>तो, आपके पास कुंजियों को उस क्रम पर मैप करने का एक तरीका है जिसमें उन्हें दिखना चाहिए। और आपका डेटाबेस उस मनमाने क्रम द्वारा आपके परिणामों को सॉर्ट और वापस कर सकता है।
यह जानकर, आप अपनी आईडी और उनकी स्थिति को एक
caseस्टेटमेंट में डाल सकते हैं, और इसे SQLorderक्लॉज में उपयोग कर सकते हैं।तो अगर आप अपने ऑब्जेक्ट्स को क्रम [2, 1, 3] में वापस चाहते हैं, तो आपका SQL ऐसा दिख सकता है:
SELECT * FROM people WHERE id IN (1, 2, 3) ORDER BY CASE id WHEN 2 THEN 0 WHEN 1 THEN 1 WHEN 3 THEN 2 ELSE 3 END;pre>इस तरह, आपके रिकॉर्ड्स सही क्रम में वापस आते हैं।
CASEप्रत्येक आईडी को उस क्रम में बदल देता है जिसमें इसे वापस किया जाना चाहिए।बेशक, यह हास्यास्पद लगता है। और आप कल्पना कर सकते हैं कि हाथ से इस तरह के क्लॉज को बनाना कितना कष्टप्रद होगा।
लेकिन आपको इसे हाथ से बनाने की ज़रूरत नहीं है। रूबी इसके लिए है:
lib/extensions/active_record/find_by_ordered_ids.rb module Extensions::ActiveRecord::FindByOrderedIds extend ActiveSupport::Concern module ClassMethods def find_ordered(ids) order_clause = "CASE id " ids.each_with_index do |id, index| order_clause << sanitize_sql_array(["WHEN ? THEN ? ", id, index]) end order_clause << sanitize_sql_array(["ELSE ? END", ids.length]) where(id: ids).order(order_clause) end end end ActiveRecord::Base.include(Extensions::ActiveRecord::FindByOrderedIds) Person.find_ordered([2, 1, 3]) # => [2, 1, 3]pre>बिल्कुल जैसा हम चाहते थे!
एक क्लीनर, MySQL-विशिष्ट तरीका
यदि आप MySQL का उपयोग करते हैं, तो इसे करने का एक क्लीनर तरीका है। MySQL में विशेष
ORDER BY FIELDसिंटैक्स है:SELECT * FROM people WHERE id IN (1, 2, 3) ORDER BY FIELD(id, 2, 1, 3);pre>आप इसे रूबी से भी जेनरेट कर सकते हैं:
lib/extensions/active_record/find_by_ordered_ids.rb module Extensions::ActiveRecord::FindByOrderedIds extend ActiveSupport::Concern module ClassMethods def find_ordered(ids) sanitized_id_string = ids.map {|id| connection.quote(id)}.join(",") where(id: ids).order("FIELD(id, #{sanitized_id_string})") end end end ActiveRecord::Base.include(Extensions::ActiveRecord::FindByOrderedIds)pre>तो, यदि आप MySQL का उपयोग कर रहे हैं, और संगतता के बारे में ज्यादा चिंतित नहीं हैं, तो यह जाने का एक अच्छा तरीका है। यह आपके लॉग्स के माध्यम से उड़ने वाले उन स्टेटमेंट्स को पढ़ने में बहुत आसान है।
जब आप रिकॉर्ड्स को एक विशिष्ट, मनमाने क्रम में प्रदर्शित करना चाहते हैं, तो आपको उन्हें रूबी में सॉर्ट करने की आवश्यकता नहीं है। एक छोटे कोड स्निपेट के साथ, आप डेटाबेस को वह करने दे सकते हैं जो यह अच्छा करता है: ढूंढना, सॉर्ट करना, और आपके ऐप को डेटा वापस करना।