【Rails】ActiveRecord入門とりあえず使えるようにまとめておく@初心者
はじめに
Railsをすこしいじり始めて、DBも使いたいのでActiveRecordをいじってみる
PHPのフレームワークではORMをほとんど使った事なかったので(喰わず嫌いで)、ちょっと新鮮だった。
とりあえず一般的というか複雑でないSQLは使えるようになりたいということでメモしておく
検証用のテーブル
・categories(動画のカテゴリー)
id | カテゴリーID | PK |
---|---|---|
name | カテゴリー名 |
・videos(動画)
id | 動画ID | PK |
---|---|---|
category_id | カテゴリーID | FK |
title | タイトル |
Modelにリレーションを設定
app/models/video.rb
class Video < ApplicationRecord belongs_to :category end
app/models/category.rb
class Category < ApplicationRecord has_many :videos end
使用例
全レコード取得
> videos = Video.all() Video Load (0.3ms) SELECT `videos`.* FROM `videos`
ORDER BY
> videos = Video.order("id desc") Video Load (0.3ms) SELECT `videos`.* FROM `videos` ORDER BY id desc
OFFSET・LIMIT
> videos = Video.order("id desc").offset(0).limit(2) Video Load (0.4ms) SELECT `videos`.* FROM `videos` ORDER BY id desc LIMIT 2 OFFSET 0
GROUP BYしてCOUNT
> videos = Video.group("videos.category_id").count (0.8ms) SELECT COUNT(*) AS count_all, videos.category_id AS videos_category_id FROM `videos` GROUP BY videos.category_id => {nil=>1, 1=>2, 2=>1}
INNER JOIN
これは負荷の面を考慮するとあまり使わないほうがよいかも。。。
> videos = Video.joins(:category) Video Load (0.4ms) SELECT `videos`.* FROM `videos` INNER JOIN `categories` ON `categories`.`id` = `videos`.`category_id` > videos[0] => #<Video id: 1, category_id: 1, title: "動画タイトル1"> > videos[0].category Category Load (0.9ms) SELECT `categories`.* FROM `categories` WHERE `categories`.`id` = 1 LIMIT 1 # ★ココでもSQLが実行される => #<Category id: 1, name: "カテゴリー1"> > videos[0].category => #<Category id: 1, name: "カテゴリー1">
INNER JOIN(IN句を使って擬似的にINNER JOIN)
> videos = Video.includes(:category) Video Load (0.7ms) SELECT `videos`.* FROM `videos` Category Load (0.4ms) SELECT `categories`.* FROM `categories` WHERE `categories`.`id` IN (1, 2) > videos[0] => #<Video id: 1, category_id: 1, title: "動画タイトル1"> > videos[0].category => #<Category id: 1, name: "カテゴリー1">
LEFT JOIN
> videos = Video.includes(:category).references(:category) SQL (0.5ms) SELECT `videos`.`id` AS t0_r0, `videos`.`category_id` AS t0_r1, `videos`.`title` AS t0_r2, `categories`.`id` AS t1_r0, `categories`.`name` AS t1_r1 FROM `videos` LEFT OUTER JOIN `categories` ON `ca\ tegories`.`id` = `videos`.`category_id` > videos[0] => #<Video id: 1, category_id: 1, title: "動画タイトル1"> > videos[0].category => #<Category id: 1, name: "カテゴリー1">
INSERT
> category = new Category(name:"テスト") > category.save
UPDATE
> category = Category.find_by_id(1) > category.name = "テスト" > category.save
おわりに
理解が浅いかとは思うが、inner joinをしたい場合にjoinsを単体で呼ぶのが危険な気がした。
ループ内でvideo.categoryを参照するタイミングでSQLが実行される
> videos = Video.joins(:category) > videos.each { |video| print video.category } Category Load (0.7ms) SELECT `categories`.* FROM `categories` WHERE `categories`.`id` = 1 LIMIT 1 #<Category:0x007ff6917902e0> Category Load (0.5ms) SELECT `categories`.* FROM `categories` WHERE `categories`.`id` = 1 LIMIT 1 #<Category:0x007ff69179ec78> Category Load (0.9ms) SELECT `categories`.* FROM `categories` WHERE `categories`.`id` = 2 LIMIT 1
まぁ、レコード数とかあらかじめわかっていれば使いどころによるのかもしれませんが。。。
以上です