N+1問題

N+1問題の基本

関連付けされている前提。
こーゆーのがあったら、
毎回each文回す度にpostテーブルを参照してしまう。

@users = User.all

@users.each do |user|
  puts user.post.content
end

ので、includesメソッドを使ってこう書き換える。
(includesメソッドとは関連テーブルの条件が一致するデータと指定テーブルのデータを取得するメソッド)

@users = User.includes(:post).all

@users.each do |user|
  puts user.post.content
end

これがN+1問題解消の基本

postからuserの情報を取得したい時は、関係性を入れ替えればOK

@posts = Post.includes(:user).all



また、postに対して複数のcommentがある場合で、
そのpostを投稿したuserのcommentを取得したい場合があるとすれば

@posts = Post.include(:user).all

@posts.each do |post|
  puts post.user.comments
end


これでは、
userとcommentの間でN+1問題が発生してしまう。
解決のためには以下のように書き換える。

@posts = Post.includes(user: :comment).all

@posts.each do |post|
  puts post.user.comments
end





その他細々した設定
* order

# posts.titleでの並び替え(title昇順)
Post.includes(:user).order(:title)

# posts.titleでの並び替え(title降順)
Post.includes(:user).order(title: :desc)
# 以下も同じ
Post.includes(:user).order("title DESC")

# posts.titleでの並び替え(user_id昇順、user_idが同じ場合はcreated_at降順)
Post.includes(:user).order(:user_id, created_at: :desc)

# users.created_atでの並び替え(created_at降順)
Post.includes(:user).order(users: {created_at: :desc})

* where

# post.user_idが3のboardを取得
Post.includes(:user).where(user_id: 3)
# 以下も同じ
Post.includes(:user).where(posts: {user_id: 3})

# user.nameが"後藤"さんのpostを取得
Post.includes(:user).where(users: {name: "後藤"})