Rails基礎 Active Recordの基本操作(メモ)
実行結果・実行されているSQLを確認するための自分用メモです。 作成~登録~更新~削除
新規オブジェクトの作成
#新規オブジェクトを作成 >> user = User.new(name: "Michael Hartl", email: "michael@example.com") (0.1ms) begin transaction => #<User id: nil, name: "Michael Hartl", email: "michael@example.com", created_at: nil, updated_at: nil>
created_at
とupdated_at
は登録日時、更新日時。このカラムとidは勝手に作ってくれる。
newしただけだと、created_at
とupdated_at
はnil
であることが確認できる。
有効性のチェック
#有効性のチェック(DBの存在チェックは行えない) >> user.valid? => true
エラーがなければtrue
、エラーが発生したらfalse
が返却される。
登録前のチェック等に。
実行結果が逆になる.invalid?
も存在する。
オブジェクトの保存
#保存 >> user.save (0.1ms) SAVEPOINT active_record_1 User Create (3.9ms) INSERT INTO "users" ("name", "email", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["name", "Michael Hartl"], ["email", "michael@example.com"], ["created_at", "2020-11-21 15:11:49.849711"], ["updated_at", "2020-11-21 15:11:49.849711"]] (0.1ms) RELEASE SAVEPOINT active_record_1 => true
INSERT
が発行されていて、DBに保存されていることがわかる。また、先ほどはnil
だったcreated_at
とupdated_at
に値が入っていることを確認できる。
またSAVEPOINT
が作成されているので、トランザクションが発行されていて、失敗した場合はロールバックしてくれるような感じがする(自分では未検証)
情報取得
#各情報の参照 >> user => #<User id: 1, name: "Michael Hartl", email: "michael@example.com", created_at: "2020-11-21 15:11:49", updated_at: "2020-11-21 15:11:49"> >> user.name => "Michael Hartl" >> user.email => "michael@example.com" >> user.updated_at => Sat, 21 Nov 2020 15:11:49 UTC +00:00
上記のINSERT
の時にはid
は含まれていなかったが、ちゃんと値が入っている。ということは内部で勝手に自動採番してくれているらしい。
createで生成と削除を同時に行う
#モデルの生成と保存を同時に行う >> User.create(name: "A Nother", email: "another@example.org") (0.1ms) SAVEPOINT active_record_1 User Create (0.1ms) INSERT INTO "users" ("name", "email", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["name", "A Nother"], ["email", "another@example.org"], ["created_at", "2020-11-21 15:12:58.282793"], ["updated_at", "2020-11-21 15:12:58.282793"]] (0.1ms) RELEASE SAVEPOINT active_record_1 => #<User id: 2, name: "A Nother", email: "another@example.org", created_at: "2020-11-21 15:12:58", updated_at: "2020-11-21 15:12:58"> >> foo = User.create(name: "Foo", email: "foo@bar.com") (0.1ms) SAVEPOINT active_record_1 User Create (0.1ms) INSERT INTO "users" ("name", "email", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["name", "Foo"], ["email", "foo@bar.com"], ["created_at", "2020-11-21 15:13:06.291513"], ["updated_at", "2020-11-21 15:13:06.291513"]] (0.1ms) RELEASE SAVEPOINT active_record_1 => #<User id: 3, name: "Foo", email: "foo@bar.com", created_at: "2020-11-21 15:13:06", updated_at: "2020-11-21 15:13:06">
save
のときは戻り値がtrue(真偽値)
だったが、create
のときは作成されたオブジェクトが返却されてくる違いがあるので、
なんでも便利だからcreate
で済まそう!とはいかなさそう。
削除
#削除 >> foo.destroy (0.1ms) SAVEPOINT active_record_1 User Destroy (0.2ms) DELETE FROM "users" WHERE "users"."id" = ? [["id", 3]] (0.1ms) RELEASE SAVEPOINT active_record_1 => #<User id: 3, name: "Foo", email: "foo@bar.com", created_at: "2020-11-21 15:13:06", updated_at: "2020-11-21 15:13:06"> >> foo => #<User id: 3, name: "Foo", email: "foo@bar.com", created_at: "2020-11-21 15:13:06", updated_at: "2020-11-21 15:13:06">
DELETE
が発行され削除されている。しかし、オブジェクト内にはメモリ上の情報が残っている。
実際に削除されたかどうかはこの方法で調べないように。(以下のfindメソッド等を使用しSELECT文を発行して確認するのが良さげ)
クラス、継承元の調べ方
#クラスと継承元を調べる >> user.name.class => String >> user.email.class => String >> user.created_at.class => ActiveSupport::TimeWithZone >> user.updated_at.class => ActiveSupport::TimeWithZone
find
#id:1を検索 >> User.find(1) User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] => #<User id: 1, name: "Michael Hartl", email: "michael@example.com", created_at: "2020-11-21 15:11:49", updated_at: "2020-11-21 15:11:49"> >> User.find(3) User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 3], ["LIMIT", 1]] Traceback (most recent call last): 1: from (irb):18 ActiveRecord::RecordNotFound (Couldn't find User with 'id'=3)
SELECT
が発行されている。find
はidで調べる用。
find_by
#特定の属性で検索 >> User.find_by(email: "michael@example.com") User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."email" = ? LIMIT ? [["email", "michael@example.com"], ["LIMIT", 1]] => #<User id: 1, name: "Michael Hartl", email: "michael@example.com", created_at: "2020-11-21 15:11:49", updated_at: "2020-11-21 15:11:49">
SELECT
が発行され、条件WHERE
がemail
となっている。任意の属性で検索する場合はfind_by
を使用する。
first
#最初のデータ >> User.first User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]] => #<User id: 1, name: "Michael Hartl", email: "michael@example.com", created_at: "2020-11-21 15:11:49", updated_at: "2020-11-21 15:11:49">
SELECT
が発行され、id
でソート(`ORDER BY~ASC``)をかけたあと、最初の1件を取得していることがわかる。
all
#すべてのデータ >> User.all User Load (0.2ms) SELECT "users".* FROM "users" LIMIT ? [["LIMIT", 11]] => #<ActiveRecord::Relation [#<User id: 1, name: "Michael Hartl", email: "michael@example.com", created_at: "2020-11-21 15:11:49", updated_at: "2020-11-21 15:11:49">, #<User id: 2, name: "A Nother", email: "another@example.org", created_at: "2020-11-21 15:12:58", updated_at: "2020-11-21 15:12:58">]>
SELECT
ですべてのデータを取得している。[["LIMIT", 11]]
の11はどこから来たのか不明…いつか調べたい。もしかしたら色々登録してて、idの最大値が入っているだけかも。
find_by_name
#名前で検索 >> User.find_by_name("Michael Hartl") User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."name" = ? LIMIT ? [["name", "Michael Hartl"], ["LIMIT", 1]] => #<User id: 1, name: "Michael Hartl", email: "michael@example.com", created_at: "2020-11-21 15:11:49", updated_at: "2020-11-21 15:11:49">
WHERE name =
で名前検索してくれる。
length
#要素の長さを取得 >> User.all.length User Load (0.2ms) SELECT "users".* FROM "users" => 2
SELECT~FROM
だけのシンプルなSQLだった。
COUNT
で件数を取得してるのかと思っていたが、どうやら違うらしい。別のところで件数を数えてくれているっぽい。
更新(save)
#更新 >> user.email = "mhartl@example.net" => "mhartl@example.net" >> user.save (0.1ms) SAVEPOINT active_record_1 User Update (0.2ms) UPDATE "users" SET "email" = ?, "updated_at" = ? WHERE "users"."id" = ? [["email", "mhartl@example.net"], ["updated_at", "2020-11-21 15:27:55.850900"], ["id", 1]] (0.1ms) RELEASE SAVEPOINT active_record_1 => true
すでにあるIDのオブジェクトをsave
すると、勝手にUPDATE
してくれるっぽい。有能。さらに、名前からして当然ではあるが、UPDATEではcreated_at
は更新されない。
取消
#save前に取消 >> user.email = "foo@bar.com" => "foo@bar.com" >> user.reload.email User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] => "mhartl@example.net"
DBにまだ保存されていないので、SQLで特に何かしているわけではないっぽい。
更新(update)
#updateで更新 >> user.update(name: "The Dude", email: "dude@abides.org") => true >> user.name => "The Dude" >> user.email => "dude@abides.org"
update
を使用すると成功したかどうかの真偽値が返却される。
検証を回避しつつ更新
#検証を回避しつつ更新 >> user.update_attribute(:name, "El Duderino") => true >> user.name => "El Duderino"
実装の中で検証が失敗するようになることもあるらしい。これから学んでいく。