Post.all.includes(:user).order(created_at: :desc)
includesメソッドとは?
このメソッドはモデル同士の関連付けを事前に取得してN+1問題を解決してくれるメソッド。指定された関連付けが最小限のクエリ回数で読み込まれるようになる。
N+1問題って?
ループ処理の中で、その都度SQLを発行してしまい、大量のSQLが発行されてしまい、パフォーマンスが低下してしまう問題。買い物をするときに商品を1つずつお会計しているようなもの。非常に効率が悪い。 例えば、投稿者(user)と投稿(post)が関連付けられているとします。postは複数あって、userに従属しているので、 userモデル
class User < ApplicationRecord has_many :posts end
postモデル
class Post < ApplicationRecord belongs_to :user end
とそれぞれのモデルに記述します。 次に、各投稿者が投稿したものを出力するプログラムを作成します。
User.all.each do |u| post_names = u.posts.pluck(:name).join(",") # pluckはテーブルから欲しいcolumnだけを情報として取ってくる。 p "#{u.name}が投稿したのは#{post_names}です。" end
として、これを実行すると、1回目のSQLでUserのデータを全て取り出したあと、Userのレコード1つ1つをu
に代入して、postsテーブルにアクセスしてデータを取り出すため、Userのデータの数分の処理を行うことになります。usersテーブル1回に対して、postsテーブルへのアクセスがN回。これがN+1問題です。
これを解決するためにincludesメソッドを使います。
includesメソッドの使い方
includesメソッドの定義ですが、
モデル名.includes(:関連名)
と書きます。ここでいうと、モデル名がUser、関連名がpostsになります。 ここの関連名はhas_many :postsと書いた:postsになります。
User.all.includes(:posts)
とすると、全ユーザーが持っている投稿を全て、N回もSQLを発行することなく出すことができる。
それでは、タイトルのPost.all.includes(:user).order(created_at: :desc)
を考えていきます。
Post.allなので、Postテーブルから全データを持ってきて、その際に付属しているuserも持ってきています。さらに、orderメソッドで並び替えをしています。その基準が作成日時を降順で、というふうになるということです。
参考
https://note.com/kentarotawara/n/nf8b27ba0e5d3 https://pikawaka.com/rails/includes https://qiita.com/massaaaaan/items/4eb770f20e636f7a1361