Railsのincludesの書き方を現役エンジニアが解説【初心者向け】
初心者向けにRailsのincludesの書き方について現役エンジニアが解説しています。Railsのincludesを使うと、必要以上にSQL文が発行されるのを防ぐことが出来ます。書き方の例としては、includesメソッドの引数にあらかじめ読み込んで置きたいテーブルを指定したりします。
テックアカデミーマガジンは受講者数No.1のプログラミングスクール「テックアカデミー」が運営。初心者向けにプロが解説した記事を公開中。現役エンジニアの方はこちらをご覧ください。 ※ アンケートモニター提供元:GMOリサーチ株式会社 調査期間:2021年8月12日~8月16日 調査対象:2020年8月以降にプログラミングスクールを受講した18~80歳の男女1,000名 調査手法:インターネット調査
Railsのincludesの書き方について解説します。
そもそもRubyについてよく分からないという方は、Rubyとは何なのか解説した記事を読むとさらに理解が深まります。
なお本記事は、TechAcademyのオンラインブートキャンプRuby講座の内容をもとに紹介しています。
今回は、Rubyに関する内容だね!
どういう内容でしょうか?
Railsのincludesの書き方について詳しく説明していくね!
お願いします!
includesとは
Railsのincludesとは、モデルの情報取得時の性能低下を防ぐために、関連付けられているモデルをあらかじめ取得しておくことです。
Railsでは「User has many articles」のようにアソシエーション(関連付け)を行うことができます。記事の作成者をまとめて表示したいような時に、何も考えずに素直に書くと次のようになるかと思います。
# models/user.rb class User < ApplicationRecord has_many :articles end # models/article.rb class Article < ApplicationRecord belongs_to :user end # 記事作成者を表示するコード articles = Article.all articles.each do |article| puts article.user.name end
このコードを実行すると、次のようにSQL文が記事数の分だけ発行されるのがわかります。
Article Load (0.3ms) SELECT articles.* FROM articles User Load (0.2ms) SELECT users.* FROM users WHERE users.id = 3 LIMIT 1 "taro" User Load (0.3ms) SELECT users.* FROM users WHERE users.id = 3 LIMIT 1 "taro" User Load (0.2ms) SELECT users.* FROM users WHERE users.id = 3 LIMIT 1 "taro" User Load (0.2ms) SELECT users.* FROM users WHERE users.id = 3 LIMIT 1 "taro" User Load (0.3ms) SELECT users.* FROM users WHERE users.id = 3 LIMIT 1 "taro"
このことをN+1問題と呼びます。同じユーザーの情報を表示するだけなのに、毎回同じSQL文を発行するのは無駄が多いですね。そこで使えるのがincludesメソッドです。
includesの書き方
引数に、事前に読み込みをしておくモデル(カラム)をシンボルで指定します。
今回の例でいくとarticles = Article.includes(:user)のように書きます。
User has many articles, Category has many articles のように、複数モデルとアソシエーションしている場合には、 articles = Article.includes(:user, :category)のようにカンマ(,)区切りで指定できます。
Group has many users, User has many articlesのように、より深い階層構造の場合には、articles = Article.includes(user: :group)というように指定できます。
上の2つの例を同時に満たすような場合は、articles = Article.includes([user: :group], :category) のように、階層関係を表す部分を[](もしくは {})で囲むことで指定できます。
includesを他のメソッド(order等)と組み合わせて使う方法
事前にデータを読み込んだ上で、さらにユーザー名で並び替えしたいような場合にはorderと組み合わせることもできます。ただし、Article.includes(:user).order(name:DESC) のように指定すると、articles.nameでの並び替えを実行しようとします。
この場合は Article.includes(:user).order(“users.name DESC”) のように、対象テーブル名とカラム名を合わせて指定する必要があるので、注意しておきましょう
またwhereなどと組み合わせる場合には、referenecesメソッドを使う必要があります。Article.includes(:user).references(:users).where(“users.id > 3”) のように指定すると、users.idが3より大きいものへの絞り込みができます。
実際に書いてみよう
Article, Userのデータを用意できたら、以下のコードを実行してみましょう。
# 記事作成者を表示するコード(includes 版) articles = Article.includes(:user) articles.each do |article| puts article.user.name end
以下の実行例を見ると、2行目で必要なuserテーブルのデータを事前に読み込んでいること、そのため記事ごとの作成者を出力するときにはSQL文が発行されていないことがわかりますね。
Article Load (0.6ms) SELECT articles.* FROM articles User Load (0.5ms) SELECT users.* FROM users WHERE users.id = 3 "taro" "taro" "taro" "taro" "taro"
N+1 問題はRailsアプリケーションの表示速度に影響するので、includesで事前に必要なデータを読み込むようにすると表示が速くなるかもしれません。覚えておくと良いでしょう。
筆者プロフィール
メンター稲員さん
フリーランスエンジニア。 経験言語:Ruby、Rails、Python、C/C++、Java、Perl、HTML/CSS3、JavaScript、CoffeeScript,Node.js。 |
内容分かりやすくて良かったです!
ゆかりちゃんも分からないことがあったら質問してね!
分かりました。ありがとうございます!
TechAcademyでは、初心者でもRuby on Railsを使ったプログラミングを習得できるオンラインブートキャンプRuby講座を開催しています。
挫折しない学習方法を知れる説明動画や、現役エンジニアとのビデオ通話とチャットサポート、学習用カリキュラムを体験できる無料体験も実施しているので、ぜひ参加してみてください。