রেলে, আপনার ডেটাবেস থেকে একগুচ্ছ রেকর্ড পাওয়া সহজ যদি আপনার কাছে তাদের আইডি থাকে:
Person.where(id: [1, 2, 3]).map(&:id) => [1, 2, 3]
কিন্তু আপনি যদি অন্যরকম রেকর্ডগুলি ফেরত পেতে চান তাহলে কী হবে৷ অর্ডার? হতে পারে আপনার সার্চ ইঞ্জিন প্রথমে সবচেয়ে প্রাসঙ্গিক আইডি ফেরত দেয়। আপনি কিভাবে রাখেন সেই ক্রমে আপনার রেকর্ড?
আপনি where
চেষ্টা করতে পারেন আবার:
Person.where(id: [2, 1, 3]).map(&:id) => [1, 2, 3]
কিন্তু সেটা মোটেও কাজ করে না। তাহলে কিভাবে করবেন আপনি সঠিক ক্রমে আপনার রেকর্ড ফিরে পেতে?
সামঞ্জস্যপূর্ণ উপায়:case
বিবৃতি
রুবির মতো, SQL case...when
সমর্থন করে বিবৃতি।
আপনি এটি প্রায়শই দেখতে পান না, তবে case...when
বিবৃতি প্রায় করতে পারে হ্যাশের মত কাজ করুন। আপনি একটি মান অন্য মান ম্যাপ করতে পারেন:
case :b
when :a then 1
when :b then 2
when :c then 3
end # => 2
সেই কেস স্টেটমেন্টটি হ্যাশের মত দেখাচ্ছে:
{
:a => 1,
:b => 2,
:c => 3
}[:b] # => 2
সুতরাং, আপনার কাছে কী ম্যাপ করার একটি উপায় আছে যাতে সেগুলি উপস্থিত হওয়া উচিত৷ এবং আপনার ডাটাবেস সেই ইচ্ছাকৃত ক্রম অনুসারে আপনার ফলাফলগুলি সাজাতে এবং ফিরিয়ে দিতে পারে৷
এটা জেনে, আপনি আপনার আইডি এবং তাদের অবস্থান একটি case
-এ রাখতে পারেন বিবৃতি, এবং এটি একটি SQL order
এ ব্যবহার করুন ধারা৷৷
সুতরাং আপনি যদি আপনার বস্তুগুলি [2, 1, 3] ক্রমে ফেরত দিতে চান, তাহলে আপনার এসকিউএল এইরকম দেখতে পারে:
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;
এইভাবে, আপনার রেকর্ডগুলি সঠিক ক্রমে ফেরত দেওয়া হয়। The CASE
প্রতিটি আইডিকে যে ক্রমে ফেরত দেওয়া উচিত সেই ক্রমে রূপান্তরিত করে৷৷
অবশ্যই, যে হাস্যকর দেখায়. এবং আপনি কল্পনা করতে পারেন যে এরকম একটি ধারা হাতে তৈরি করা কতটা বিরক্তিকর হবে।
কিন্তু আপনার নেই৷ এটি হাতে তৈরি করতে। রুবি এর জন্য এটিই:
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]
ঠিক যেভাবে আমরা এটা চেয়েছিলাম!
একটি ক্লিনার, MySQL-নির্দিষ্ট উপায়
আপনি যদি MySQL ব্যবহার করেন তবে এটি করার একটি পরিষ্কার উপায় রয়েছে। MySQL এর রয়েছে বিশেষ ORDER BY FIELD
সিনট্যাক্স:
SELECT * FROM people
WHERE id IN (1, 2, 3)
ORDER BY FIELD(id, 2, 1, 3);
আপনি রুবি থেকেও এটি তৈরি করতে পারেন:
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)
সুতরাং, আপনি যদি MySQL ব্যবহার করেন এবং সামঞ্জস্য নিয়ে খুব বেশি চিন্তিত না হন, তাহলে এটি একটি ভাল উপায়। এই বিবৃতিগুলি আপনার লগের মাধ্যমে উড়ে যাওয়ায় এটি পড়া অনেক সহজ৷
৷আপনি যখন একটি নির্দিষ্ট, নির্বিচারে রেকর্ডগুলি প্রদর্শন করতে চান, তখন আপনাকে সেগুলিকে রুবিতে সাজাতে হবে না। একটি ছোট কোড স্নিপেটের সাহায্যে, আপনি ডাটাবেসকে তা করতে দিতে পারেন যা ভাল:আপনার অ্যাপে ডেটা খুঁজে বের করা, সাজানো এবং ফেরত দেওয়া।