N+1 問題
[N+1 問題]とは?
必要以上にSQLが実行されてしまい、パフォーマンスが落ちること。
ex)掲示板の一覧画面に個別の掲示板を全て表示する場合(以下コードを参照)
個別の掲示板を取得するのにSQLを1回実行
取得した個別の掲示板からユーザー情報を個別の掲示板の数だけN回取得するのにSQLをN回実行する(取得した個別の掲示板モデルとユーザーモデルはアソシエーション関係にあり、個別の掲示板モデルに外部キーでuser_idがある)
[app/controller/board_controller.rb] def index @boards = Board.all end
[app/views/index.html.erb] <% @boards.each do |board| %> <%= render partial: "board", locals: { board: board } %> <% end %>
[N+1 問題の解消法]
controllerで全掲示板を取得する際に、includesメソッドを利用する。
includesメソッドは、アソシエーションの関連付けを事前に取得してN +1問題を解決するメソッドです。
[includesメソッドの使い方]
モデル名.includes(:関連名)
※注意
関連名は、テーブル名の事ではない。
ex)
def index @boards = Board.all.includes(:user).order(created_at: :desc) end
個別掲示板を掲示板一覧画面でeach文で回さないようにする。
[views ファイル] <%= render partial: 'board', collection: @boards %>
上記のコマンドは、以下の条件を満たすと[views ファイル1]のように省略できる。 ・呼び出す部分テンプレートがviewsフォルダ内にあるboardsフォルダに存在する ・部分テンプレート名が_comment.html.erbである ・部分テンプレート内で使う変数がboardである
[views ファイル1] <%= render @boards %>
上記のように、コントローラーに記載した全掲示板を取得する変数をrenderにそのまま渡すと、同じディレクト下の@変数単数形の部分テンプレートが参照される。 @変数はeachされて部分テンプレート名に入る。 ex) [_board.html.erb]を[boardsディレクトリ]下に持ってきて掲示板の一覧を表示することができる。
参考記事:
【Rails】N+1問題って何?原因と対処法を徹底解説! | Pikawaka - ピカ1わかりやすいプログラミング用語サイト
まるで魔法だな(パーシャルをrenderし繰り返し処理をする) - Qiita
render先に変数が上手く渡らないときに確認すること - Qiita
【Rails基礎】ややこしい部分テンプレートの省略形について簡単にまとめてみた|TechTechMedia
【Rails】部分テンプレートの使い方を徹底解説! | Pikawaka - ピカ1わかりやすいプログラミング用語サイト