কম্পিউটার

কিভাবে রেল স্কোপ প্রিলোড করবেন

এই নিবন্ধটি কোরিয়ান ভাষায়ও উপলব্ধ, ধন্যবাদ Soonsang Hong!

রেলের স্কোপগুলি আপনার পছন্দের রেকর্ডগুলি খুঁজে পাওয়া সহজ করে তোলে:

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 টি এসকিউএল কলের পরিবর্তে, আমরা শুধুমাত্র দুটি করেছি।

(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. Rails অভিনব ব্যতিক্রম পৃষ্ঠা কিভাবে কাজ করে

  2. রেলে ফ্ল্যাশ বার্তাগুলি কীভাবে ব্যবহার করবেন

  3. রুবি দিয়ে কীভাবে কমান্ড-লাইন অ্যাপ্লিকেশন (সিএলআই) তৈরি করবেন

  4. কিভাবে একটি রেল অ্যাপ্লিকেশনে OmniAuth-Twitter ব্যবহার করবেন