🐼

注文一覧(管理者側) topに表示。N+1クエリ問題

2024/06/27に公開
  • 管理側で注文履歴一覧をtop画面で表示させる

コントローラー

admin/homescontroller
class Admin::HomesController < ApplicationController
  def top
    @orders = Order.includes(:customer, :order_details).order(created_at: :desc).page(params[:page]).per(10)
  end
end
  • 解説

@orders = Order.
@order変数にOrderモデルからデータを取得して代入

includes(:customer, :order_details)

  • (:customer, :order_details)はモデルの関連づけからきてる
app/models/order.rb
class Order < ApplicationRecord
belongs_to :customer
has_many :order_details
end
  • N+1クエリ問題を避けるため(下記に詳しく)

  • order(created_at: :desc)作成日時の降順で注文を並び替える。最新の注文が最初に表示されるようになる。どんな時も[先頭はorderでいい。]

注文履歴一覧(top)ビュー

admin/homes/top.html.erb
<div class="container">
  <div class="row">
   <div class="mx-auto offset-lg-2">


    <h4>注文履歴一覧</h4>

    <table class="table">
      <thead>
        <tr>
          <td class="field">
            <th>購入日時</th>
            <th>購入者</th>
            <th>注文個数</th>
            <th>注文ステータス</th>
          </td>
        </tr>
      </thead>

      <tbody>
        <% @orders.each do |order| %>
        <tr>
         <!--日時を注文履歴詳細へリンク-->
         <td class="field">
           <td>
            <%= link_to admin_order_path(order) do %>
            <%= order.created_at.strftime("%Y/%m/%d %H:%M") %>
            <% end %>
          </td>
          <td><%= order.customer.last_name %><%= order.customer.first_name %></td>
          <td><%= order.order_details.sum(:amount) %></td>
          <td><%= order.order_status_i18n %></td>
        </tr>
       <% end %>

      <td><%= paginate(@orders) %></td>
      </tbody>
    </table>

    </div>
  </div>
</div>

N+1クエリ問題とは

データベースにアクセスする時の非効率なクエリ発行によるパフォーマンス問題のこと。
関連するデータを事前ロードするメソッドとして"includes"が必要...
これを使うと、アプリケーションのレスポンス速度が向上するみたい。

N+1クエリ問題の例

orders = Order.all
orders.each do |order|
 puts order.customer.name
end

1.Order.all:全注文を取得する1回のクエリ。
2.各注文に対して、関連する顧客を取得するためのクエリ。
(10件の注文がある場合は、1と2合わせて、11回のクエリが発行。)

これが、N+1クエリ問題。

order(created_at: :desc)作成日時の降順で注文を並び替える。最新の注文が最初に表示されるようになる。

ふーん。

Discussion