最初の5つの投稿のユーザー名を取得する必要があるとします。以下のクエリをすばやく作成して、週末を楽しんでください。
posts = Post.limit(5)
posts.each do |post|
puts post.user.name
end
良い。しかし、クエリを見てみましょう
Post Load (0.5ms) SELECT `posts`.* FROM `posts` LIMIT 5
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
1 query
すべてのposts
を取得するには および1 query
users
を取得するには 投稿ごとに合計6 queries
になります 。 2 queries
で同じことを行う以下のソリューションを確認してください :
posts = Post.includes(:user).limit(5)
posts.each do |post|
puts post.user.name
end
#####
Post Load (0.3ms) SELECT `posts`.* FROM `posts` LIMIT 5
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` IN (1, 2)
少し違いがあります。 includes(:posts)
を追加します あなたの質問に、そして問題は解決しました。すばやく、素敵で、簡単です。
ただし、includes
を追加するだけではいけません 正しく理解せずにクエリで。 includes
の使用 joins
を使用 状況によっては相互結合が発生する可能性があり、ほとんどの場合、それは必要ありません。
含まれているモデルに条件を追加する場合は、それらを明示的に参照する必要があります 。例:
User.includes(:posts).where('posts.name = ?', 'example')
エラーがスローされますが、これは機能します:
User.includes(:posts).where('posts.name = ?', 'example').references(:posts)
includes
に注意してください association names
で動作します references
the actual table name
が必要です 。