接著上一篇我們繼續說明用 ORM 來操作 CRUD 的部分 關於讀取的部分還可以怎麼去找到,還有後面的 update 及 delete 的說明。
用 find 來找 id
Model.find(:id)
find_by 可以找特定欄位的資訊是否有對應的資料Model.find_by(欄位名: 值)
兩者的差異:
3.0.0 :001 > a1 = Article.find(1)
Article Load (0.2ms) SELECT "articles".* FROM "articles" WHERE "articles"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
=> #<Article id: 1, title: "文章1", content: "進入ruby世界說hello world", created_at: "2022-10-03 12:41:21.8330...
3.0.0 :002 > a2 = Article.find_by(id: 2)
Article Load (0.3ms) SELECT "articles".* FROM "articles" WHERE "articles"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]]
=> #<Article id: 2, title: "文章2", content: "CRUD是什麼?", created_at: "2022-10-04 09:31:49.206583000 +0000",...
3.0.0 :003 > a2 = Article.find_by(title: "文章2")
Article Load (0.3ms) SELECT "articles".* FROM "articles" WHERE "articles"."title" = ? LIMIT ? [["title", "文章2"], ["LIMIT", 1]]
=> #<Article id: 2, title: "文章2", content: "CRUD是什麼?", created_at: "2022-10-04 09:31:49.206583000 +0000",...
找不到資料時的差別
4.3.0.0 :001 > a3 = Article.find_by(id: 3)
Article Load (0.3ms) SELECT "articles".* FROM "articles" WHERE "articles"."id" = ? LIMIT ? [["id", 3], ["LIMIT", 1]]
=> nil
4.3.0.0 :002 > a3 = Article.find(3)
Article Load (0.3ms) SELECT "articles".* FROM "articles" WHERE "articles"."id" = ? LIMIT ? [["id", 3], ["LIMIT", 1]]
Traceback (most recent call last):
1: from (irb):13:in `<main>'
ActiveRecord::RecordNotFound (Couldn't find Article with 'id'=3)
3.0.0 :014 >
where 可以搭配一些篩選條件,比如過 id > 1,內容包含某些資料之類的條件等等,
我們再建立第3筆文章資料,然後透過where篩選 id > 1 看看吧。
3.0.0 :001 > Article.all
Article Load (0.3ms) SELECT "articles".* FROM "articles" /* loading for inspect */ LIMIT ? [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<Article id: 1, title: "文章1", content: "進入ruby世界說hello world", created_at: "2022-10-03 12:41:21.833091000 +0000", updated_at: "2022-10-03 12:41:21.833091000 +0000">, #<Article id: 2, title: "文章2", content: "CRUD是什麼?", created_at: "2022-10-04 09:31:49.206583000 +0000", updated_at: "2022-10-04 09:31:49.206583000 +0000">, #<Article id: 3, title: "文章3", content: "MVC是什麼?", created_at: "2022-10-04 10:10:05.905998000 +0000", updated_at: "2022-10-04 10:10:05.905998000 +0000">]>
4.3.0.0 :002 > Article.where("id > 1")
Article Load (0.4ms) SELECT "articles".* FROM "articles" WHERE (id > 1) /* loading for inspect */ LIMIT ? [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<Article id: 2, title: "文章2", content: "CRUD是什麼?", created_at: "2022-10-04 09:31:49.206583000 +0000", updated_at: "2022-10-04 09:31:49.206583000 +0000">, #<Article id: 3, title: "文章3", content: "MVC是什麼?", created_at: "2022-10-04 10:10:05.905998000 +0000", updated_at: "2022-10-04 10:10:05.905998000 +0000">]>
可以看到根據條件就撈出id=2、id=3兩篇文章的資料。
先找到要的資料,然後修改欄位數值,再用save更新
a1 = Article.find_by(id: 1)
a1.title = "第一篇文章"
a1.save
只更新單一欄位的值 (attribute 是單數),注意會跳過驗證
a1.update_attribute(:title, "第一篇文章")
兩個方法只是名稱不同,都可一次更新多個欄位,且不需要再呼叫 save 方法
a1.update(title: "第一篇文章", content: "你知道要怎麼印出'hello world'嗎?")
a1.update_attributes(title: "第一篇文章", content: "你知道要怎麼印出'hello world'嗎?")
實際在 console 裡面操作的情形
3.0.0 :001 > a1 = Article.find(1)
(0.4ms) SELECT sqlite_version(*)
Article Load (0.1ms) SELECT "articles".* FROM "articles" WHERE "articles"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
=> #<Article id: 1, title: "文章1", content: "進入ruby世界說hello world", created_at: "2022-10-03 12:41:21.8330...
3.0.0 :002 > a1.update_attribute(:title, "第一篇文章")
TRANSACTION (0.1ms) begin transaction
Article Update (0.7ms) UPDATE "articles" SET "title" = ?, "updated_at" = ? WHERE "articles"."id" = ? [["title", "第一篇文章"], ["updated_at", "2022-10-04 10:20:44.717780"], ["id", 1]]
TRANSACTION (0.9ms) commit transaction
=> true
3.0.0 :003 > a1.title = "改回文章1"
=> "改回文章1"
3.0.0 :004 > a1.save
TRANSACTION (0.1ms) begin transaction
Article Update (0.7ms) UPDATE "articles" SET "title" = ?, "updated_at" = ? WHERE "articles"."id" = ? [["title", "改回文章1"], ["updated_at", "2022-10-04 10:21:31.485894"], ["id", 1]]
TRANSACTION (1.0ms) commit transaction
=> true
刪除有 delete
及 destroy
兩種方法,可以將資料刪除。
a1 = Article.find_by(id: 1)
a1.destroy
a1.delete
## 等同於從 model 直接找id進行刪除
Article.destroy(1)
Article.delete(1)
終端機操作的顯示
3.0.0 :001 > a1 = Article.find(1)
Article Load (0.3ms) SELECT "articles".* FROM "articles" WHERE "articles"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
=> #<Article id: 1, title: "改回文章1", content: "進入ruby世界說hello world", created_at: "2022-10-03 12:41:21....
3.0.0 :002 > a1.destroy
TRANSACTION (0.1ms) begin transaction
Article Destroy (0.7ms) DELETE FROM "articles" WHERE "articles"."id" = ? [["id", 1]]
TRANSACTION (0.9ms) commit transaction
=> #<Article id: 1, title: "改回文章1", content: "進入ruby世界說hello world", created_at: "2022-10-03 12:41:21.833091000 +0000", updated_at: "2022-10-04 10:21:31.485894000 +0000">
3.0.0 :003 > Article.delete(2)
Article Destroy (1.9ms) DELETE FROM "articles" WHERE "articles"."id" = ? [["id", 2]]
=> 1
3.0.0 :009 > a2 = Article.find(2)
Article Load (0.3ms) SELECT "articles".* FROM "articles" WHERE "articles"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]]
Traceback (most recent call last):
1: from (irb):9:in `<main>'
ActiveRecord::RecordNotFound (Couldn't find Article with 'id'=2)
destroy 跟 delete 的差別:
- destroy 方法執行的時候,會執行完整的回呼(Callback)
- delete 方法直接執行 SQL 的 delete from 語法,不會進行任何回呼。
參考資料: