Computer >> कंप्यूटर ट्यूटोरियल >  >> प्रोग्रामिंग >> Ruby

Rails Scopes में महारत हासिल करें: रिकॉर्ड्स को कुशलतापूर्वक प्रीलोड करना

यह लेख कोरियाई में भी उपलब्ध है, सूनसांग हॉन्ग का धन्यवाद!

Rails के scopes आपके द्वारा चाहने वाले रिकॉर्ड्स को ढूंढना आसान बनाते हैं:

app/models/review.rb
class Review < ActiveRecord::Base belongs_to :restaurant scope :positive, -> { where("rating > 3.0") } end 

irb(main):001:0> Restaurant.first.reviews.positive.count Restaurant Load (0.4ms) SELECT `restaurants`.* FROM `restaurants` ORDER BY `restaurants`.`id` ASC LIMIT 1 (0.6ms) SELECT COUNT(*) FROM `reviews` WHERE `reviews`.`restaurant_id` = 1 AND (rating > 3.0) => 5 

लेकिन अगर आप उनके साथ सावधान नहीं हैं, तो आप अपने ऐप के प्रदर्शन को गंभीर रूप से नुकसान पहुंचाएंगे।

क्यों? आप वास्तव में एक scope को प्रीलोड नहीं कर सकते। तो अगर आपने कुछ रेस्तरां को उनकी सकारात्मक समीक्षाओं के साथ दिखाने की कोशिश की:

irb(main):001:0> restauraunts = Restaurant.first(5) irb(main):002:0> restauraunts.map do |restaurant| irb(main):003:1* "#{restaurant.name}: #{restaurant.reviews.positive.length} positive reviews." irb(main):004:1> end Review Load (0.6ms) SELECT `reviews`.* FROM `reviews` WHERE `reviews`.`restaurant_id` = 1 AND (rating > 3.0) Review Load (0.5ms) SELECT `reviews`.* FROM `reviews` WHERE `reviews`.`restaurant_id` = 2 AND (rating > 3.0) Review Load (0.7ms) SELECT `reviews`.* FROM `reviews` WHERE `reviews`.`restaurant_id` = 3 AND (rating > 3.0) Review Load (0.7ms) SELECT `reviews`.* FROM `reviews` WHERE `reviews`.`restaurant_id` = 4 AND (rating > 3.0) Review Load (0.7ms) SELECT `reviews`.* FROM `reviews` WHERE `reviews`.`restaurant_id` = 5 AND (rating > 3.0) => ["Judd's Pub: 5 positive reviews.", "Felix's Nightclub: 6 positive reviews.", "Mabel's Burrito Shack: 7 positive reviews.", "Kendall's Burrito Shack: 2 positive reviews.", "Elisabeth's Deli: 15 positive reviews."] 

हां, यह एक N+1 क्वेरी है। धीमे Rails ऐप्स का सबसे बड़ा कारण।

आप इसे बहुत आसानी से ठीक कर सकते हैं, हालांकि, अगर आप रिश्ते को एक अलग तरीके से सोचते हैं।

Scopes को Associations में बदलें

जब आप Rails एसोसिएशन मेथड्स का उपयोग करते हैं, जैसे belongs_to और has_many, तो आपका मॉडल आमतौर पर ऐसा दिखता है:

app/models/restaurant.rb
class Restaurant < ActiveRecord::Base has_many :reviews end 

लेकिन अगर आप दस्तावेज़ीकरण देखते हैं, तो आप देखेंगे कि वे अधिक कर सकते हैं। आप उन मेथड्स में अन्य पैरामीटर पास कर सकते हैं और बदल सकते हैं कि वे कैसे काम करते हैं।

scope सबसे उपयोगी में से एक है। यह पहले वाले scope की तरह ही काम करता है:

app/models/restaurant.rb
class Restaurant < ActiveRecord::Base has_many :reviews has_many :positive_reviews, -> { where("rating > 3.0") }, class_name: "Review" end 

irb(main):001:0> Restaurant.first.positive_reviews.count Restaurant Load (0.2ms) SELECT `restaurants`.* FROM `restaurants` ORDER BY `restaurants`.`id` ASC LIMIT 1 (0.4ms) SELECT COUNT(*) FROM `reviews` WHERE `reviews`.`restaurant_id` = 1 AND (rating > 3.0) => 5 

अब, आप includes के साथ अपने नए एसोसिएशन को प्रीलोड कर सकते हैं:

irb(main):001:0> restauraunts = Restaurant.includes(:positive_reviews).first(5) Restaurant Load (0.3ms) SELECT `restaurants`.* FROM `restaurants` ORDER BY `restaurants`.`id` ASC LIMIT 5 Review Load (1.2ms) SELECT `reviews`.* FROM `reviews` WHERE (rating > 3.0) AND `reviews`.`restaurant_id` IN (1, 2, 3, 4, 5) irb(main):002:0> restauraunts.map do |restaurant| irb(main):003:1* "#{restaurant.name}: #{restaurant.positive_reviews.length} positive reviews." irb(main):004:1> end => ["Judd's Pub: 5 positive reviews.", "Felix's Nightclub: 6 positive reviews.", "Mabel's Burrito Shack: 7 positive reviews.", "Kendall's Burrito Shack: 2 positive reviews.", "Elisabeth's Deli: 15 positive reviews."] 

6 SQL कॉल के बजाय, हमने केवल दो किए।

(class_name का उपयोग करके, आप एक ही ऑब्जेक्ट के लिए कई एसोसिएशन रख सकते हैं। यह बहुत काम आता है।)

डुप्लीकेशन के बारे में क्या?

यहां अभी भी एक समस्या हो सकती है। where("rating > 3.0") अब आपके Restaurant क्लास पर है। अगर आप बाद में सकारात्मक समीक्षाओं को rating > 3.5 में बदलते, तो आपको इसे दो बार अपडेट करना पड़ता!

यह और खराब हो जाता है: यदि आप उन सभी सकारात्मक समीक्षाओं को भी प्राप्त करना चाहते हैं जो किसी व्यक्ति ने कभी छोड़ी हैं, तो आपको उस scope को User क्लास पर भी डुप्लिकेट करना होगा:

app/models/user.rb
class User < ActiveRecord::Base has_many :reviews has_many :positive_reviews, -> { where("rating > 3.0") }, class_name: "Review" end 

यह बहुत DRY नहीं है।

इसके आसपास एक आसान तरीका है, हालांकि। where के अंदर, आप Review क्लास में जोड़े गए positive scope का उपयोग कर सकते हैं:

app/models/restaurant.rb
class Restaurant < ActiveRecord::Base has_many :reviews has_many :positive_reviews, -> { positive }, class_name: "Review" end 

इस तरह, विचार कि क्या एक समीक्षा को सकारात्मक समीक्षा बनाता है, अभी भी केवल एक जगह पर है।

Scopes महान हैं। सही जगह पर, वे आपके डेटा को क्वेरी करना आसान और मजेदार बना सकते हैं। लेकिन अगर आप N+1 क्वेरी से बचना चाहते हैं, तो आपको उनके साथ सावधान रहना होगा।

तो, अगर एक scope आपको परेशानी देना शुरू कर देता है, तो इसे एक एसोसिएशन में लपेटें और इसे प्रीलोड करें। यह बहुत अधिक काम नहीं है, और यह आपको SQL कॉल का एक गुच्छा बचाएगा।

  1. रेल्स में फ्लैश मैसेजेस मास्टर करें: एक पूर्ण मार्गदर्शिका रेल्स में फ्लैश मैसेजेस मास्टर करें: एक पूर्ण मार्गदर्शिका

    फ्लैश मैसेजेस क्या हैं? एक फ्लैश मैसेज आपके रेल्स एप्लिकेशन के उपयोगकर्ताओं के साथ जानकारी संवाद करने का एक तरीका है ताकि वे जान सकें कि उनके कार्यों के परिणामस्वरूप क्या होता है। उदाहरण संदेश: पासवर्ड सही ढंग से बदला गया (पुष्टि) उपयोगकर्ता नहीं मिला (त्रुटि) आप इन फ्लैश मैसेजेस को अपने कंट्रोलर्

  1. शक्तिशाली रूबी CLI टूल्स बनाएं: चरण-दर-चरण गाइड शक्तिशाली रूबी CLI टूल्स बनाएं: चरण-दर-चरण गाइड

    बहुत से लोग भूल जाते हैं कि रूबी वेब एप्लिकेशन के अलावा भी चीजें कर सकता है। इस लेख में, मैं आपको दिखाना चाहता हूं कि इस कमी को दूर करने के लिए कमांड-लाइन एप्लिकेशन कैसे बनाया जाए! यहाँ कुछ कमांड-लाइन एप्लिकेशन हैं जिनसे आप परिचित हो सकते हैं: psql rails bundler gem git कमांड-लाइन एप्लिकेशन बनाने

  1. OmniAuth-Twitter के साथ Rails में ट्विटर लॉगिन एकीकृत करें: चरण-दर-चरण मार्गदर्शिका OmniAuth-Twitter के साथ Rails में ट्विटर लॉगिन एकीकृत करें: चरण-दर-चरण मार्गदर्शिका

    इस ट्यूटोरियल में, आप सीखेंगे कि अपने एप्लिकेशन के उपयोगकर्ताओं को उनके ट्विटर खाते का उपयोग करके लॉग इन करने की अनुमति कैसे दें। OAuth जैसे टूल के साथ ऐसा करना आसान हो गया है। आप OmniAuth-Twitter का उपयोग करेंगे, जिसमें OmniAuth के लिए ट्विटर रणनीति शामिल है। चलिए शुरू करते हैं! शुरुआत करना अपना R