読者です 読者をやめる 読者になる 読者になる

Railsガイド メモ 13

programming reading books

7.12.3 結合されたテーブルで条件を指定する

time_range = (Time.now.midnight - 1.day)..Time.now.midnight
Client.joins(:orders).where('orders.created_at' => time_range)

または

Client.joins(:orders).where(orders: { created_at: time_range })


7.13.1 複数の関連付けを一括で読み込む

irb(main):010:0> Category.includes(articles: [{ comments: :guest }, :tags]).first
  Category Load (0.9ms)  SELECT  `categories`.* FROM `categories` ORDER BY `categories`.`id` ASC LIMIT 1
  Article Load (0.9ms)  SELECT `articles`.* FROM `articles` WHERE `articles`.`category_id` = 21
  Comment Load (6.8ms)  SELECT `comments`.* FROM `comments` WHERE `comments`.`article_id` IN (10003, 10005, 10019, ・・・, 10298, 10300)
  Guest Load (18.5ms)  SELECT `guests`.* FROM `guests` WHERE `guests`.`comment_id` IN (1054, 1437, ・・・, 10292, 10298, 10300)
=> #<Category id: 21, name: "政治", created_at: "2017-02-27 23:17:27", updated_at: "2017-02-27 23:17:27">

7.13.2 関連付けの一括読み込みで条件を指定する

Article.includes(:comments).where(comments: { visible: true })

このコードは、LEFT OUTER JOINを含むクエリを1つ生成します。

SELECT `articles`.`id`          AS t0_r0, 
       `articles`.`title`       AS t0_r1, 
       `articles`.`content`     AS t0_r2, 
       `articles`.`category_id` AS t0_r3, 
       `articles`.`created_at`  AS t0_r4, 
       `articles`.`updated_at`  AS t0_r5, 
       `comments`.`id`          AS t1_r0, 
       `comments`.`body`        AS t1_r1, 
       `comments`.`article_id`  AS t1_r2, 
       `comments`.`visible`     AS t1_r3, 
       `comments`.`created_at`  AS t1_r4, 
       `comments`.`updated_at`  AS t1_r5 
FROM   `articles` 
       LEFT OUTER JOIN `comments` 
       ON `comments`.`article_id` = `articles`.`id` 
WHERE  `comments`.`visible` = 1; 

joinsメソッドを使用していたら、代りにINNER JOINを使用するクエリが生成されていたでしょう。

Article.joins(:comments).where(comments: { visible: true})
SELECT `articles`.* 
FROM   `articles` 
       INNER JOIN `comments` 
       ON `comments`.`article_id` = `articles`.`id` 
WHERE  `comments`.`visible` = 1; 

where 条件がない場合は、通常のクエリが 2 セット生成されます。

Article.includes(:comments)
SELECT `articles`.* FROM `articles`;

SELECT `comments`.* 
  FROM   `comments` 
  WHERE  `comments`.`article_id` 
  IN ( 10001, 10002, 10003, 10004, ・・・, 10298, 10299, 10300 ) ;

7.14.3 スコープのマージ default_scope で定義した条件が、scope や where で定義した条件よりも先に評価される


本日は、7.15 まで読了。次は、7.16 「メソッドチェインを理解する」 から