実務でまさかのincludesメソッドに戸惑う
「この画面の情報をスプレッドシートに出力しておいて」
「はーい」
(データを取ってくるだけなら余裕だろ、、、)
(あれ、関連するモデル多すぎじゃね?)
(関連するモデルに関連するモデルも取得、、あれ、、頭が、、、)
って感じで整理できていない部分がありましたので、今回まとめておきます。
前提
- モデルの関連付けだけをテーマに書きます。
- includesする際、単数形か複数形かはアソシエーションによって判断します。
- N+1問題を解決するためにincludesします。( 参考記事 )
今回例示するモデル
- Tweets:ツイート
- Users:ユーザー
- Comments:ツイートに対するコメント
- Tags:ツイートにつけるタグ
- Addresses:ユーザーの住む住所
ここでは便宜上、関連するモデルを子モデル、子モデルに関連するモデルを孫モデルと呼ぶことにします。
① 子モデルが1つの場合
Tweet.includes(:user)
こちらはTweetに紐づくUser(子)を取得します。
② 子モデルが2つの場合
Tweet.includes(:user, :tags)
こちらはTweetに紐づくUser(子)およびTag(子)を取得します。 ([:user, :tags])
と書く場合もあるので、それは所属するチームでの決まりに従うと良いでしょう。
③ 子モデル・孫モデルが1セットの場合
Tweet.includes(user: :address)
:(コロン)の位置に注意です。こちらはTweetに紐づくUser(子)とそのUserに紐づくAddress(孫)を取得します。
孫モデルが複数ある場合
Tweet.includes(user: [:address, :comments])
明示的に[]が必要です。こちらはTweetに紐づくUser(子)とそのUserに紐づくAddress(孫)およびComment(孫)を取得します。
③ 子モデル・孫モデルが1セットと子モデルが1つの場合
Tweet.includes(:tags, user: :address)
注意すべき点は、孫モデルまで参照するものを後ろに記述することです。こちらはTweetに紐づくTag(子)およびUser(子)とそのUserに紐づくAddress(孫)を取得します。
※ Tweet.includes(user: :address, :tags)
とすると、筆者の場合 SyntaxError: unexpected ')', expecting =>
と表示されてしまいます。
※ もし子モデル・孫モデルのセットが増えたなら、後ろに加えれば大丈夫です。
【募集】 STIをincludesする場合
今現在まだ実務で出会っていませんが、STIを参照する際のincludesの形はどうなるのだろう、、と今から不安です。もし、参考記事などございましたらご教授いただければ幸いです。
これからも新しい書き方を見つけたら更新していきます
実務未経験から働き始めて約1週間。まだまだこんなものではないと思いますので、気付き次第随時更新していきます。