【Rails】ActiveRecordのよく使うメソッド集(モデル検索、テーブル結合など)

目次

ActiveRecordには、データベースからオブジェクトを取り出す検索メソッドが多数用意されています。

検索メソッドはwhereやgroupといったコレクションを返したり、ActiveRecord::Relationのインスタンスを返します。

またfindやfirstなどの1つのエンティティを検索するメソッドの場合、そのモデルのインスタンスを返します。

単一のオブジェクトを取り出す

find

主キーで検索

findメソッドで複数のオブジェクトを取得

findメソッドでマッチするレコードが見つからない場合、
ActiveRecord::RecordNotFound例外が発生します。

first

デフォルトでは主キー順の最初のレコードを取得

firstメソッドで返すレコードの最大数を指定して取得

orderを使って順序を変更した場合、
firstメソッドはorderで指定された属性にしたがって
最初のレコードを取得

firstメソッドは、モデルにレコードが1つもない場合にnilを返します。
このとき例外は発生しません。

last

デフォルトでは主キーの順序にしたがって最後のレコードを取得

lastメソッドは、モデルにレコードが1つもない場合にnilを返します。
このとき例外は発生しません。

find_by

与えられた条件にマッチするレコードのうち、最初のレコードを取得

find_byメソッドは、モデルにレコードが1つもない場合にnilを返します。
このとき例外は発生しません。

条件

where

返されるレコードを制限するための条件を指定します。
SQL文でいうWHEREの部分に相当します。

・NOT条件
SQLのNOTクエリはwhere.notで表せます。

・OR条件
1つ目のリレーションでorメソッドを呼び出し、そのメソッドの引数に
2つ目のリレーションを渡します。

並び順

データベースから取り出すレコードを特定の順序で並び替え

取り出すレコード数の上限を指定

limit

主キー順の最初から数えて5件のレコードを取得

テーブルの結合

joins

デフォルトは内部結合(INNER JOIN)
内部結合は「結合条件に一致するレコードのみを取得」
この場合だとpostsテーブルのuser_idと、usersテーブルのidを指定

left_joins

左外部結合(LEFT OUTER JOIN)
「結合条件に一致するレコード」と「左側のテーブルにしかないレコード」を取得

関連付けを一括読み込みする

includes

一括読み込み(eager_loading)とは、Model.findによって返されるオブジェクトに関連付けられたレコードを読み込むためのメカニズムであり、できるだけクエリの回数を減らすようにします。

・N+1クエリ問題
以下のコードは、ユーザーを10人検索して郵便番号を表示します。
usersテーブルとaddressesテーブルの関係は1対1とします。

このコードには問題があります。実行されたクエリの数が無駄に多いことです。
最初にユーザーを10人検索するのにクエリを1回発行し、次にそこから住所を取り出すのに
クエリを10回発行するので、合計11回のクエリが発行されます。

・N+1クエリ問題を解決する
ActiveRecordは、読み込まれるすべての関連付けを事前に指定することができます。
これはincludesを指定することで実現できます。
includesを指定すると、ActiveRecordは指定されたすべての関連付けが最小限のクエリ回数で
読み込まれるようにしてくれます。

上の例でいうと、User.limit(10)を書き直して、住所が一括で読み込まれるようにします。

最初の例では11回もクエリが発行されましたが、今回の例では2回にまで減りました。

最後に

自分自身、無駄に多くクエリを発行するコードを書いてしまうことがありました。今回学んだことを生かして、モデル検索の性能にも気をつけたいと思います。

以上です!