iT邦幫忙

2022 iThome 鐵人賽

DAY 20
0
Modern Web

一探紅寶石的神秘面紗 - Ruby 及 Rails入門介紹 系列系列 第 20

Day 20 - 進入Rails世界必須懂:Model 相關介紹 及 CRUD (下)

  • 分享至 

  • xImage
  •  

接著上一篇我們繼續說明用 ORM 來操作 CRUD 的部分 關於讀取的部分還可以怎麼去找到,還有後面的 update 及 delete 的說明。

更精準的讀取 find & find_by & Where

find & find_by

用 find 來找 id
Model.find(:id)
find_by 可以找特定欄位的資訊是否有對應的資料
Model.find_by(欄位名: 值)

兩者的差異:

  • find 只能找 id,find_by 可以找任何資料表內的東西
  • find 找不到會出錯, find_by 只會回傳 nil
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

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兩篇文章的資料。

Update 更新

用 save 更新

先找到要的資料,然後修改欄位數值,再用save更新

a1 = Article.find_by(id: 1)
a1.title = "第一篇文章"
a1.save

使用 update_attribute

只更新單一欄位的值 (attribute 是單數),注意會跳過驗證

a1.update_attribute(:title, "第一篇文章")

使用 update & update_attributes

兩個方法只是名稱不同,都可一次更新多個欄位,且不需要再呼叫 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 刪除

刪除有 deletedestroy 兩種方法,可以將資料刪除。

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 語法,不會進行任何回呼。

參考資料:

  1. Rails Guide
  2. 為你自己學 Ruby on Rails

上一篇
Day 19 - 進入Rails世界必須懂:Model 相關介紹 及 CRUD (上)
下一篇
Day 21 - 進入Rails世界必須懂:Migration
系列文
一探紅寶石的神秘面紗 - Ruby 及 Rails入門介紹 系列30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言