Railsのincludesの書き方を現役エンジニアが解説【初心者向け】

初心者向けにRailsのincludesの書き方について現役エンジニアが解説しています。Railsのincludesを使うと、必要以上にSQL文が発行されるのを防ぐことが出来ます。書き方の例としては、includesメソッドの引数にあらかじめ読み込んで置きたいテーブルを指定したりします。

TechAcademyマガジンはオンラインのプログラミングスクールTechAcademy [テックアカデミー]が運営する教育×テクノロジーのWebメディアです。初心者でもすぐ勉強できる記事が2,000以上あります。

Railsのincludesの書き方について解説します。

Rubyについてそもそもよく分からないという方は、Rubyとは何なのか解説した記事をまずご覧ください。

 

なお本記事は、TechAcademyのWebアプリケーションオンラインブートキャンプの内容をもとに紹介しています。

田島悠介

今回は、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) のように、階層関係を表す部分を[](もしくは {})で囲むことで指定できます。

[PR] Rubyのプログラミングで挫折しない学習方法を動画で公開中

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で事前に必要なデータを読み込むようにすると表示が速くなるかもしれません。覚えておくと良いでしょう。

 

筆者プロフィール

メンター稲員さん

フリーランスエンジニア。
大手SEからフリーランスのWeb系エンジニアにジョブチェンジ。

経験言語:Ruby、Rails、Python、C/C++、Java、Perl、HTML/CSS3、JavaScript、CoffeeScript,Node.js。
おうち大好きマンです。

 

大石ゆかり

内容分かりやすくて良かったです!

田島悠介

ゆかりちゃんも分からないことがあったら質問してね!

大石ゆかり

分かりました。ありがとうございます!

TechAcademyでは初心者でも最短4週間でエンジニアになれるRuby on Railsオンラインブートキャンプを開催しています。

現役エンジニアがパーソナルメンターとして受講生に1人ずつつき、マンツーマンのメンタリングで学習をサポートし、最短4週間でオリジナルWebサービスを開発することが可能です。

また、現役エンジニアから学べる無料のプログラミング体験会も実施しているので、ぜひ参加してみてください。