0
0

More than 1 year has passed since last update.

【Rails】過去の記事がN+1問題そのものだったので修正する

Last updated at Posted at 2022-09-09

目的

現役Webエンジニアの知り合いに過去に書いた記事を自慢げに見せたところ、
N+1問題って知ってる?
と言われました。

クロノスタシスよろしく、「知らな~い」と答えたところ、下記記事を紹介して頂いたのでこちらを参考に修正しました。

早速修正だ!

そもそもN+1問題というのは、has_manyで紐づけしたテーブルを呼び出す際に、いちいち全てのデータを参照して引っ張ってくることだと理解しました。
これによってデータベースへのアクセスにかかる時間が長くなり、サーバに負荷がかかってしまいます。

モデルで主従関係を明らかにする

過去記事では触れていなかったモデルについて言及します。
今回、Genreモデルが主、Hogeモデルが従の関係になっているので、

genre.rb
has_many :hoges
hoge.rb
belongs_to :genre

とします。
モデルの主従関係については過去に記事を書いていますので、こちらを参考にしてください。

余談ですが、has_manyはその要素が沢山あるので複数形belongs_toは1つの要素だけなので単数形で書くのが一般的のようです。

コントローラでincludesメソッドを使用する

モデルの主従関係を元に、アクション内で呼び出す変数も修正します。

修正前

# アクション内で
@genres = Genre.all

修正後

# アクション内で
@genres = Genre.includes(:hoges)

これにより、ビューファイルでHogeモデルを呼び出したいときは
@genresに対してhogesというメソッドを使用できるようになりました。

ビューファイルの修正

以上を踏まえ、ビューファイルを修正していきます。

修正前

<% @genres.each do |genre| %>
  <p><%= genre.name %></p>
  <% hoges = Hoge.where(genre_id: genre.id) %> # ここでN+1が発生
  <table>
  <tr>
    <td>id</td><td>content</td>
  </tr>
  <% hoges.each do |hoge| %>
    <tr>
      <td><%= hoge.id %></td>
      <td><%= hoge.content %></td>
    </tr>
  <% end %>
  </table>
<% end %>

修正後

ビューファイル
<% @genres.each do |genre| %>
  <p><%= genre.name %></p>
  # hogesの定義を削除
  <table>
  <tr>
    <td>id</td><td>content</td>
  </tr>
  <% genre.hoges.each do |hoge| %> # genreに紐づくhogesを呼び出す
    <tr>
      <td><%= hoge.id %></td>
      <td><%= hoge.content %></td>
    </tr>
  <% end %>
  </table>
<% end %>

具体的には、hogesを定義した一文の削除と、genreからの紐づけによるhogeの呼び出しをおこないました。
これにより、N+1問題は解消されました。

まとめ

今回は
原因のひとつとして、ビューファイルでdbにアクセスしようとしたことが挙げられます。
変数の定義やそれに伴うdbへのアクセスは、モデルファイルやコントローラファイルといった、上位階層でおこなうべきだと気付かされました。

また本内容を指摘して頂いた経験から、独学で開発を進める上で自分よりも経験値のある(世の中の98%のエンジニアがそう)方と会うことの大切さを身をもって知りました。
コミュニティって大事ですね!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0