Railsスコープをプリロードする方法
この記事は、Soonsang Hongのおかげで、韓国語でも利用できます!
Railsのスコープを使用すると、必要なレコードを簡単に見つけることができます。
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クエリです。 Railsアプリが遅い最大の原因。
ただし、関係について別の方法で考えると、これは非常に簡単に修正できます。
belongs_to
などのRails関連付けメソッドを使用する場合 およびhas_many
、モデルは通常次のようになります:
class Restaurant < ActiveRecord::Base
has_many :reviews
end
ただし、ドキュメントを確認すると、さらに多くのことができることがわかります。これらのメソッドに他のパラメーターを渡して、それらの動作を変更することができます。
スコープコード> 最も便利なものの1つです。
スコープ
と同じように機能します 以前から:
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
これで、 include
を使用して新しい関連付けをプリロードできます :
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呼び出しではなく、2回だけ実行しました。
( class_name
を使用 、同じオブジェクトに複数の関連付けを行うことができます。これはかなり頻繁に役立ちます。)
複製はどうですか?
ここにはまだ問題があるかもしれません。 where( "rating> 3.0")
これでレストランクラスに参加しました。後で肯定的なレビューをrating>3.5
に変更した場合 、2回更新する必要があります!
さらに悪いことに、ある人がこれまでに残した肯定的なレビューもすべて取得したい場合は、そのスコープをUserクラスにも複製する必要があります:
class User < ActiveRecord::Base
has_many :reviews
has_many :positive_reviews, -> { where("rating > 3.0") }, class_name: "Review"
end
あまり乾燥していません。
ただし、これを回避する簡単な方法があります。 where
の内部 、positive
を使用できます Reviewクラスに追加したスコープ:
class Restaurant < ActiveRecord::Base
has_many :reviews
has_many :positive_reviews, -> { positive }, class_name: "Review"
end
そうすれば、アイデア レビューを肯定的なレビューにする理由は、まだ1か所だけです。
スコープは素晴らしいです。適切な場所で、データのクエリを簡単かつ楽しくすることができます。ただし、N + 1クエリを避けたい場合は、注意する必要があります。
したがって、スコープが問題を引き起こし始めた場合は、スコープを関連付けにラップしてプリロードします 。それほど手間がかからず、SQL呼び出しを大幅に節約できます。
-
Rubyを使用してコマンドラインアプリケーション(CLI)を構築する方法
多くの人は、RubyがWebアプリケーションではないことを実行できることを忘れています。この記事では、それを改善するのに役立つコマンドラインアプリケーションを構築する方法を紹介したいと思います! 使い慣れているコマンドラインアプリケーションは次のとおりです。 psql rails bundler gem git コマンドラインアプリケーションを構築する方法はたくさんあります。この記事では、そのうちの3つに焦点を当てます。 あなたは学ぶつもりです : ARGVアレイ OptParseライブラリ トールの宝石 始めましょう! RubyARGV定数 コマンドラインア
-
RailsアプリケーションでOmniAuth-Twitterを使用する方法
このチュートリアルでは、アプリケーションのユーザーがTwitterアカウントを使用してログインできるようにする方法を学習します。これを行うには、OAuthなどのツールを使用すると簡単になります。 OmniAuthのTwitter戦略を含むOmniAuth-Twitterを利用します。 飛び込みましょう! はじめに Railsアプリケーションを生成することから始めます。ターミナルから、コマンドを実行して実行します。 rails new Tuts-Social -T Gemfileを開き、ブートストラップgemを追加します。 #Gemfile...gem bootstra