Railsで複数テーブルのjoins/includesとwhere検索

スポンサーリンク

Rails の ActiveRecord で複数の関連する DB テーブル(モデル)を joins/includes させて、where 検索を行う方法です。結構難しかった。

— 環境 —
Ruby 2.2.3
Rails 4.2.4

【お知らせ】 英単語を画像イメージで楽に暗記できる辞書サイトを作りました。英語学習中の方は、ぜひご利用ください!
画像付き英語辞書 Imagict | 英単語をイメージで暗記
【開発記録】
英単語を画像イメージで暗記できる英語辞書サービスを作って公開しました
スポンサーリンク

複数の関連するDBテーブル/モデルの例

以下のようなモデルのクラス群があるとします。

以上のように「Country <- Prefecture <- City <- Town」というような関連になっている複数のモデルで、これらの複数の関連するDBテーブルを対象として、ActiveRecord の includes/joins を使って where 検索する方法です。

includes, joins で複数テーブルを where 検索

Town クラス(towns テーブル)に、City の名前(cities テーブルの name カラム)で検索する scope を作成してみます。同時に towns テーブルに、cities, prefectures, countries テーブルを joins/includes させる。

複数の関連テーブルを joins/includes する際には、親子関係となっている場合には、上記のようにシンボルを使ったハッシュ/配列を組み合わせて書きます。

親子関係じゃない並列の関係の場合は、配列の中に並べて書く。以下参考。
Railsで複数テーブルに跨ってincludesする – 飲んだり寝たり

また、実際の開発では N+1 問題の回避のために、joins ではなくて includes を使うことも多いかと思いますが、includes を使う場合は references メソッドに where 句で参照するテーブル名を指定します。

【追記 2015/10/17】
includes + references を使うと、SQL では LEFT OUTER JOIN が発行されます。場合によっては LEFT OUTER JOIN では都合が悪い場合もあるだろうから、INNER JOIN で eager loading する方法がないかを調べました。

結論から言いますと…

を使うと可能なことが分かりました。この方法を使うと、INNER JOIN を使いつつ N+1 問題も回避できるはず。詳しくは以下を参照お願いします。

Rails – INNER JOIN で eager loading – Qiita
Rails – ActiveRecordのjoinsとpreloadとincludesとeager_loadの違い – Qiita
Ruby – joinsを使ってeager loadingをする方法 – Qiita
【追記ここまで】

スポンサーリンク
パーフェクト Ruby on Rails は、最近読んだ Rails 本の中では一番役に立った本です。Chef や Capistrano など Rails と共によく使用される技術にも触れてあります。Ruby on Rails 4 アプリケーションプログラミングは、入門的な内容で Rails の機能全体を網羅されています。
 
スポンサーリンク

Leave Your Message!