Model
前面的章節有提到過 Model 其實就是一個幫忙與資料庫溝通的地方,他既不是資料庫(Database)也不是資料表(Table),Model 可以當成一個抽象類別,負責跟實體的資料表溝通。
CRUD
先來簡單說文解字一下這四個基本的字,”CRUD”的意義吧!主要是描述下面這四個字。
- Create (C) 新增,建立資料,將定義好的欄位寫入對應的值
- Read (R) 讀取,讀取資料,查詢資料的相關內容
- Update (U) 更新,更新特定欄位的資料
- Delete (D) 刪除,刪除資料
我們可以透過基本的 ORM 操作來感受一下 rails 如何用到上面的這些操作資料的動作吧,操作前先簡單解釋一下相關的專有名詞,也是許多面試常常會問到的觀念。
ORM?
ORM 是 Object Relational Mapping 的縮寫,翻譯成「物件關聯對映」。如果想要存取資料庫裡的內容,在以前必須自己撰寫資料庫查詢語言(SQL)對資料庫進行查詢,但透過 ORM 的技術包裝之後,可以讓我們用操作「物件」的方式來操作資料庫。
Active Record?
Active Record 是一種設計模式,MVC 中的 Model 就是根據 Active Record 的 模式設計出來的,另外一種常見的說法是 Active Record 是 ORM 的實作方式。
Active Record 的好處
- 使用物件導向的方式來操作資料表
- 展現 Model 之間的關係
- 表示出相關 Model 之間的繼承關係
- 在存取到資料庫之前驗證資料
用 ORM 方式來操作 CRUD
建立 model
我們先建立一個文章 Article 的 Model,在終端機輸入下面指令就可以建立,同時也定義 2 個欄位給他,分別是
- string 型態的
title
- text 型態的
content
1
| rails g model Article title:string content:text
|
會產生對應的資料表,我們可以在 app/db 下面看到 migration 檔案,migration 會記錄建立 table 的經過,具備哪些欄位,我們在輸入 db:migrate 將 table 具現化,才能對裡面的內容進行操作
1 2 3 4 5 6 7 8 9 10
| class CreateArticles < ActiveRecord::Migration[6.1] def change create_table :articles do |t| t.string :title t.text :content
t.timestamps end end end
|
從上面看似乎還會有 timestamps 這個資料欄位,但其實總共還會多出 id
、timestamps
,timestamps 在經過轉換之後,會產生兩個名為 created_at 跟 updated_at 的時間欄位,分別會在資料「新增」及「更新」的時候,把當下的時間寫入,可以作為一個紀錄,讓你知道某筆資料的變動。
id 欄位則是在 Migration 沒辦法看到任何資訊,因為這是 Rails 自動幫每個資料表加的流水編號欄位,也稱為資料表的主鍵(Primary Key)。方便讓你知道目前這個 table 建立過幾筆資料,查找上也會比較方便。
可以從下面預設的 app/db/development.sqlite3 的檔案看到實際所有的欄位
Create 建立
可以從 rails console 裡面來操作實際建立一筆資料,終端機輸入 rails console
or rails c
之後
我們可以使用 active record 提供給我們的方法
- create
- new
兩者的差別是,new 完需要 save 才會存入資料庫,create 則會直接寫入。
我們用 create 的方式來看一下。
1 2 3 4 5 6
| 3.0.0 :001 > Article.create(title:"文章1",content:"進入ruby世界說hello world") (0.3ms) SELECT sqlite_version(*) TRANSACTION (0.0ms) begin transaction Article Create (0.4ms) INSERT INTO "articles" ("title", "content", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["title", "文章1"], ["content", "進入ruby世界說hello world"], ["created_at", "2022-10-03 12:41:21.833091"], ["updated_at", "2022-10-03 12:41:21.833091"]] TRANSACTION (0.4ms) 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-03 12:41:21.833091000 +0000">
|
可以看到上面 有出現 INSERT INTO “articles” 這個 SQL 語法,表示已經將檔案寫入資料庫
Read 讀取
想要取得資料表中的第一筆或最後一筆資料,可使用 first
或 last
方法,我們用 last 來讀看看
1 2 3 4 5 6
| 4.3.0.0 :002 > a1 = Article.last Article Load (0.5ms) SELECT "articles".* FROM "articles" ORDER BY "articles"."id" DESC LIMIT ? [["LIMIT", 1]] => #<Article id: 1, title: "文章1", content: "進入ruby世界說hello world", created_at: "2022-10...
4.3.0.0 :003 > a1 => #<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">
|
讀取最後一筆 (目前也只有一筆) 資料並且放入變數 a1 中,可以看到顯示出所有這筆資料的欄位及值,除了我們說的定義的欄位之外還有多出那 3 個前面提到的欄位。
我們也用一下 new 方法讓大家看一下,需要再用 save 進行資料的寫入
1 2 3 4 5 6 7 8 9
| 3.0.0 :001 > a2 = Article.new(title:"文章2", content:"CRUD是什麼?") (0.6ms) SELECT sqlite_version(*) => #<Article id: nil, title: "文章2", content: "CRUD是什麼?", created_at: nil, updated_at: nil>
4.3.0.0 :002 > a2.save TRANSACTION (0.2ms) begin transaction Article Create (1.1ms) INSERT INTO "articles" ("title", "content", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["title", "文章2"], ["content", "CRUD是什麼?"], ["created_at", "2022-10-04 09:31:49.206583"], ["updated_at", "2022-10-04 09:31:49.206583"]] TRANSACTION (0.8ms) commit transaction => true
|
看到 save 之後有回傳一個 true 表示有成功寫入。
也可以來用 first 抓看看我們的資料,先用 Article.all 看一下全部是有兩筆資料,然後可以用 first,也可以用 first(number),括號內可以指定要從第一筆開始抓幾筆。
1 2 3 4 5 6 7 8 9 10 11
| 3.0.0 :004 > Article.all Article Load (0.5ms) SELECT "articles".* FROM "articles" 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">
3.0.0 :004 > Article.first Article Load (0.3ms) SELECT "articles".* FROM "articles" ORDER BY "articles"."id" ASC LIMIT ? [["LIMIT", 1]] => #<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">
4.3.0.0 :005 > Article.first(2) Article Load (0.3ms) SELECT "articles".* FROM "articles" ORDER BY "articles"."id" ASC LIMIT ? [["LIMIT", 2]] => [#<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
|
下篇再來繼續說明一些讀取的方法、更新及刪除的部分。
---
參考資料:
- Rails Guide
- 為你自己學 Ruby on Rails
- wiki ORM