यह लेख कोरियाई में भी उपलब्ध है, सूनसांग हाँग का धन्यवाद!
स्कोप्स आपके डेटाबेस से सही ऑब्जेक्ट्स प्राप्त करने का एक शानदार तरीका है:
class Review < ActiveRecord::Base scope :most_recent, -> (limit) { order("created_at desc").limit(limit) } end
आप स्कोप का उपयोग इस तरह करेंगे:
@recent_reviews = Review.most_recent(5)
उस स्कोप को कॉल करना, हालांकि, Review पर एक नियमित क्लास मेथड को कॉल करने जैसा बिल्कुल दिखता है। और इसे क्लास मेथड के रूप में बनाना भी आसान है:
def self.most_recent(limit) order("created_at desc").limit(limit) end
@recent_reviews = Review.most_recent(5)
तो जब आप नियमित रूबी क्लास मेथड्स का उपयोग कर सकते हैं तो आप स्कोप का उपयोग क्यों करेंगे? क्या इन पूरी तरह से अलग, लेकिन समतुल्य, अवधारणाओं को अपने दिमाग में रखना उचित है? क्या होगा यदि आप अजीब बग्स में पड़ते हैं? क्या यह सारा अतिरिक्त सामान वही चीज नहीं है जो रेल्स को सीखना कठिन बनाता है?
कब स्कोप का उपयोग करना क्लास मेथड के बजाय समझदारी होगी?
जब हमारे पास पहले से ही क्लास मेथड्स हैं तो स्कोप्स का उपयोग क्यों करें?
क्या होगा यदि आप किसी विशिष्ट तिथि के बाद लिखी गई सभी समीक्षाओं को प्राप्त करना चाहते हैं? लेकिन यदि कोई तिथि निर्दिष्ट नहीं की गई है, तो आप सभी समीक्षाओं को वापस करना चाहते हैं?
स्कोप के रूप में, यह ऐसा दिखता है:
scope :created_since, ->(time) { where("reviews.created_at > ?", time) if time.present? }
आसान है, है ना? क्लास मेथड के बारे में क्या?
def self.created_since(time) if time.present? where("reviews.created_at > ?", time) else all end end
इसमें थोड़ा अतिरिक्त काम लगता है। स्कोप्स स्कोप्स वापस करना पसंद करते हैं, इसलिए उन्हें एक साथ चेन करना आसान होता है:
Review.positive.created_since(5.days.ago)
लेकिन क्लास मेथड को उसी तरह काम करने के लिए, आपको विशेष रूप से उस मामले को संभालना होगा जहां time nil है। अन्यथा, कॉलर को यह पता लगाना होगा कि उसके पास एक वैध, चेनेबल स्कोप है या नहीं।
मेथड्स जो हमेशा एक ही तरह का ऑब्जेक्ट लौटाते हैं, वास्तव में उपयोगी होते हैं। आपको एज केस या एरर के बारे में ज्यादा चिंता करने की ज़रूरत नहीं है। आप मान सकते हैं कि आपको हमेशा एक ऐसा ऑब्जेक्ट वापस मिलेगा जिसका आप उपयोग कर सकते हैं।
यहां, इसका मतलब है कि आप `nil` मान वापस आने की चिंता किए बिना स्कोप्स को एक साथ चेन कर सकते हैं।
ऐसे तरीके अभी भी हैं जिनसे आप यह मानकर कि आपको हमेशा एक स्कोप वापस मिलेगा, इस धारणा को तोड़ सकते हैं:
scope :broken, -> { "Hello!!!" }
irb(main):001:0> Review.broken.most_recent(5) NoMethodError: undefined method `most_recent' for "Hello!!!":String
लेकिन वास्तविक कोड में ऐसा कभी नहीं हुआ।
मुझे स्कोप्स के बारे में सबसे ज्यादा जो पसंद है वह यह है कि वे इरादा व्यक्त करते हैं। आप अपने कोड पढ़ने वाले अगले व्यक्ति को बता रहे हैं, "यह मेथड चेनेबल है, अंततः ऑब्जेक्ट्स की एक सूची में बदल जाएगा, और आपको ऑब्जेक्ट्स का सही सेट चुनने में मदद करेगा।" यह एक सामान्य क्लास मेथड की तुलना में बहुत अधिक कहता है।
कब आपको स्कोप के बजाय क्लास मेथड का उपयोग करना चाहिए?
क्योंकि स्कोप्स इरादा व्यक्त करते हैं, मैं जब भी सरल, बिल्ट-इन स्कोप्स (जैसे where और limit) को अधिक जटिल स्कोप्स में चेन करता हूँ, तब उनका उपयोग करता हूँ। ऑब्जेक्ट्स का सही समूह ढूंढना वही है जिसके लिए स्कोप्स डिज़ाइन किए गए थे।
दो अपवाद हैं:
- जब मुझे स्कोप्स को प्रीलोड करने की आवश्यकता होती है, तो मैं उन्हें असोसिएशन में बदल देता हूँ।
- जब मैं बिल्ट-इन स्कोप्स को बड़े स्कोप्स में चेन करने से अधिक करता हूँ, तो मैं क्लास मेथड्स का उपयोग करता हूँ।
जब आपका स्कोप लॉजिक जटिल हो जाता है, तो क्लास मेथड इसे रखने के लिए सही जगह लगता है।
क्लास मेथड के अंदर, आप आसानी से रूबी कोड को डेटाबेस कोड के साथ मिला सकते हैं। यदि आपके पास सॉर्टिंग कोड है जिसे रूबी में लिखना आसान है, तो आप अपने ऑब्जेक्ट्स को उनके डिफ़ॉल्ट क्रम में प्राप्त कर सकते हैं, और उन्हें सही क्रम में रखने के लिए sort_by का उपयोग कर सकते हैं।
या, यदि आप विशेष रूप से चालाक महसूस कर रहे हैं, तो एक क्लास मेथड कुछ अलग-अलग स्थानों से डेटा ले सकता है: आपका डेटाबेस, Redis, या एक एक्सटर्नल API या सर्विस। फिर, यह उन सभी को ऑब्जेक्ट्स के एक संग्रह में असेंबल कर सकता है जो महसूस होता है जैसे एक स्कोप जिसे एक सरणी में बदल दिया गया हो।
तब भी, अपने सेलेक्टिंग, सॉर्टिंग, जॉइनिंग, और फ़िल्टरिंग कोड को स्कोप्स के अंदर रखना अच्छा है। फिर, अपने क्लास मेथड के अंदर उन स्कोप्स का उपयोग करें। आप एक स्पष्ट क्लास मेथड और पूरे ऐप में उपयोग करने योग्य स्कोप्स के साथ समाप्त होंगे।
स्कोप्स मेरी पसंदीदा रेल्स सुविधाओं में से एक है। आप कुछ शक्तिशाली चीजें कर सकते हैं - रेल्स मॉडल्स को सॉर्ट और फ़िल्टर करने पर मेरा लेख पढ़ें एक विशेष रूप से उपयोगी स्कोप उदाहरण देखने के लिए।
और स्कोप्स का उपयोग करने में महारत हासिल करने का एक बहुत सरल तरीका है: छोटे, केंद्रित ऐप्स के अंदर उनके साथ खेलें। Practicing Rails के मुफ्त नमूना अध्याय आपको दिखाएगा कि कैसे। इसे देखें!