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

रेल स्कोप को प्रीलोड कैसे करें

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

रेल का दायरा आपके इच्छित रिकॉर्ड ढूंढना आसान बनाता है:

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

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

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

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 क्वेरी है। धीमी रेल ऐप्स का सबसे बड़ा कारण।

आप इसे बहुत आसानी से ठीक कर सकते हैं, हालांकि, यदि आप संबंध के बारे में अलग तरीके से सोचते हैं।

स्कोप को एसोसिएशन में बदलें

जब आप रेल एसोसिएशन विधियों का उपयोग करते हैं, जैसे 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") अब आपकी रेस्टोरेंट क्लास में है। अगर आपने बाद में सकारात्मक समीक्षाओं को rating > 3.5 . में बदल दिया है , आपको इसे दो बार अपडेट करना होगा!

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

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

यह बहुत शुष्क नहीं है।

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

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

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

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

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


  1. रेल में फ्लैश संदेशों का उपयोग कैसे करें

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

  1. रूबी के साथ कमांड-लाइन एप्लिकेशन (सीएलआई) कैसे बनाएं?

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

  1. रेल एप्लिकेशन में OmniAuth-Twitter का उपयोग कैसे करें

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