やっぱりよくわかっていなかったので、メモ。
要は joinsしたテーブルを検索状態にしたいのだけど…というやつです。
目的
Record は Category に紐付いていて、recordの検索の条件に categoryの中にあるカラムを使いたくなりました。
activerecordだけで調べてピンとこなかったので、ここぞとばかりにsqlから学び直すことに。
目的を達成しそうなsql
SELECT "records".*, "categories"."is_payment"
FROM "records" INNER JOIN "categories"
ON "records"."category_id" = "categories"."id"
WHERE "categories"."is_payment" = false;
するとこんな感じの返しがきた。
id | money | date | card | memo | created_at | updated_at | category_id | user_id | is_payment
----+--------+------------+------+------+----------------------------+----------------------------+-------------+---------+------------
41 | 290000 | 2016-04-10 | f | | 2016-04-27 09:52:07.124605 | 2016-04-27 09:52:07.124605 | 21 | 1 | f
(1 row)
これをactive recordに変換する
まずjoinsから確認してみた。.to_sqlメソッドを使うと発行されるsqlを見ることができるので便利だった。
$ puts Record.all.joins(:category).to_sql
SELECT "records".* FROM "records" INNER JOIN "categories" ON "categories"."id" = "records"."category_id"
=> nil
意外と発行してもらいたいことと近そうだ。これにwhereをつけていい感じにはきだしてくれたぽい。
$ puts Record.all.joins(:category).where("categories.is_payment = ?", false).to_sql
SELECT "records".* FROM "records" INNER JOIN "categories" ON "categories"."id" = "records"."category_id" WHERE (categories.is_payment = 'f')
結果は
Record.all.joins(:category).where("categories.is_payment = ?", false)
Record Load (0.5ms) SELECT "records".* FROM "records" INNER JOIN "categories" ON "categories"."id" = "records"."category_id" WHERE (categories.is_payment = 'f')
=> [#<Record:0x007fdbbf55a2b0
id: 41,
money: 290000,
date: Thu, 28 Apr 2016,
card: false,
memo: "",
created_at: Thu, 28 Apr 2016 07:02:28 UTC +00:00,
updated_at: Thu, 28 Apr 2016 07:02:28 UTC +00:00,
category_id: 21,
user_id: 1>]
で無事に取れた様子。
where(“categories.is_payment = ?”, false) この部分を文字列じゃない形で渡してあげたい。
追記: 2016/04/28 16:29
と思って調べてみたら、やっぱりあった。
Record.all.joins(:category).where(categories: { is_payment: false} ) という書き方で同等になる模様。
sql書かないと覚えなさそうなので、こんな感じでいろいろ遊んで覚えていきたい。