好!完成了 ! Tweets 專案

我們這組是全端開發 Tweets 專案,謝謝組員 Allen / Elliot 兩位夥伴一起完成這次專案。
我主要負責功能,因為功能彼此交織,有點難細分就是誰負責哪些功能。
不過在此附上專案成果:
LiveDemoGitHub 連結

tweets

事情沒有那麼簡單

首先,這是第一次團體協作,有共有三個組員,我們素未謀面,要達到牢不可破的默契,是有點難度,中間有摩擦、有衝突、有放下,我想這才是團體專案最重要的功課。這篇文章會分成三個部分,首先,有幾件事情必須在正式實作前完成,第二,實作過程,與最後,未來如何做得更好。

Definition of Done (DoD)

acceptance
首先,我們透過 User Story 制定出 Definition of Done(DOD)

大家一定要對於目標有一定共識,不然開發的過程會增加許多溝通成本,那制定後,一定就沒有問題嗎?也不是這樣說,有時候計劃會趕不上變化,後面再多做說明。

User Flowchart

user_flowchart
透過教案提供的 UI 設計圖,我們需要清楚知道,網站的流程會如何進行,按下 Button 後會轉跳什麼頁面,點擊畫面的連結會轉跳到什麼頁面 …,我覺得在繪製 User Flowchart 的過程可以更快的瞭解專案的全貌,視覺得呈現專案的功能與需求。

ERD

tweets_erd
ERD 幫助視覺化呈現 Model 關聯性,對於後續建立 Model 關聯性很有幫助。

進入開發階段

進入開發階段,紀錄幾個我比較印象深刻的經驗:

tweets_trello

快馬加鞭

當完成上述的前置作業,只剩一個多禮拜的開發時間。由於有 sprint check-in 的時間壓力,因此,除了加速開發速度,沒有別的。但加速開發速度,勢必有些畫面細節無法兼顧,謝謝 Allen 一肩扛起畫面的調整。

Code Convention

coding

每個人都有不同的風格,可以看到不同的寫法,但是以整個專案來說,會有點難以維護。但是因為時間有限,要在短時間擬定出一致的 Coding Style 會有難度。也只能邊做邊改,盡量維持一致的 Code Convention。

隨時更新進度

每日的 Standup meeting 讓夥伴掌握彼此進度,在透過 Trello 管理 tickets,哪些事情還沒做,哪些事情需要先做…

昨天做了哪些事 | 今天預計要完成的事 | 有沒有遇到困難

但這個過程中有發現,有時候遇到問題不一定會及時提出,會先嘗試自己解決,但未必能解決。最好的辦法還是設定停損點,花點時間釐清問題,假如仍然不行,就必須趕快丟出來詢問老師或同學。

找蟲

寫程式有趣的是自己覺得沒有問題,但畫面有問題,來吧,來找蟲吧~
到後期對於整個專案更了解,所以找蟲的時間可以省下不少,而且很有成就感,但反觀專案前期,在茫茫程式碼裡找蟲,結果通常是找到自己。

反思

其實專案進行的過程中已經有一些摩擦,有些人可能會怕,想說會吵架,好可怕。但要銘記一件事在心:目標導向為主!

Git 情境與指令要熟

Git 協作過程一定會碰到衝突,解完衝突,功能壞了,畫面歪了。或是離主幹太遠,回不來…太多情境都是之前一個人沒辦法實驗的。等到遇到又有點不知所措,只好趕快 google 指令。

確認認知

有時候雖然有明確的目標(DOD),但彼此的認知可能會不一樣,可能有些人會對於畫面比較要求,有些人可能對於功能的完整性更在乎。到最後一定要有個取捨,取捨已可以成功交出專案為目標。剩下的,針鋒相對就沒有那麼重要。因此,有衝突很正常,但最重要的是成功交付專案。因此誰在乎畫面,或誰在乎功能,就不是問題了。

這次團體專案協作,技術層面不需要太擔心,因為有不熟的技術,趕快回頭看教案內容,看看網路上有沒有相關的 simple code 參考,要是卡關太久,馬上詢問老問。

最後,相信所有的事,當下看起來很難,事過境遷後,就換下一關,然後會發現自己升等了,轉換到不同層級關卡的循環。

企業參訪:AmazingTalker

我滑就報名了這次 AC 舉辦的企業參訪,在去公司之前我對於 AmazingTalker 粗淺的認識停留在 阿滴跟滴妹?印象中,某次經過忠孝復興還是哪有非常大面的捷運廣告,但那已經很久遠了。

行前為了確保我對公司有一定認識,我註冊了公司的帳號密碼,我沒有開始第一堂課(汗顏),因為我現在很拮据阿(哭哭)

進入主題了

活動主要有三個認識,

  1. 從Abner的角度認識AmazingTalker、
  2. 從Tony的角度認識CTO角色與從管理角度來看對於工程師的期待,
  3. 最後是與同學間交流分享。

第一個認識,Abner開場就告訴大家不要隨便創業,但從他的分享聽得出來他真的“不是隨便”創業,公司照顧同事需求,也願意提供同事更棒的工作環境(托育空間的想法真的很友善),更重要的是公司更勇於嘗試。Abner提到AmazingTalker之所以成功在於對於嘗試的迭代速度很快,發現有錯誤,要先退一步找出錯誤的原因,然後規劃優化的方法,盡快修正。這一點與寫程式很像,程式在一定架構下可以透過不斷嘗試不同做法,但不是所有做法都是“好的”做法,透過別人的建議,可以在一起討論出更好的做法。

第二個認識,Tony 分享工程師團隊的組織編制,AT 在團隊中安排 mentor 的制度,讓剛踏入全新領域的新進 Junior 工程師很有安全感,可以在有資深前輩的帶領下,更了解公司產品、怎麼優化自己程式碼的品質、一起尋找解決的問題本質,找出最適合解決方案。在這樣的合作關係下,可以在公司學到很多專業技術(公司還有圖書館,未來有機會進入 AT 就可以省一筆技術類的書費)。

第三個認識,同學間的交流分享,這次小組討論有十個成員,大家來自不同背景,有學校老師、半導體工程師、業務等等,轉職對大家來說都是一個新的嘗試,雖然都有面臨到一些困境,但大家都滿正向面對挑戰,在轉職的路上有機會和同學交流很溫暖,倒也不是相互取暖,而是有些掙扎已經走過可以有機會分享給其他人,也些可能還沒走過,但未來要是遇到也比較不擔心。
昨天晚上收穫滿滿,讓我可以更冷靜的面對接下來的挑戰。

Git

建立上游連線

從遠端專案 fork 下來後,如果上游專案有更新怎麼辦?

  1. 先確定目前遠端分支狀態 git remote -v
  2. 新增遠端分支位置 upstream
  • git remote add upstream [GitHub HTTPS/SSH URL]
  1. 檢查上游專案有沒有更新 git fetch upstream
  • 假如有更新 -> git merge upstream/branch_name

個人專案 - 記帳本

這是一個使用者可以自行註冊 / 使用第三方等方法登入的記帳工具,是 side-project 的雛形。

為什麼會選擇這個專案

身為一個熱愛自己動手做實用的軟體工具的工程師,在 MVC 架構下,可以好好練習 CRUD 的各種變化,也是一個可以好好玩各種可能性的練習,在練習的過程中加入一些新套件的實驗與應用,是最有趣的部分。

所以對我來說,只要是日常需要的軟體工具,都是一個選擇專案的原因。

使用什麼技術

這次專案的開法是以 Express 為全端開發,Handlebars 處理畫面 ,資料庫是使用 MongoDB ,這次專案的新嘗試是 Passport 套件的 Facebook / Google 登入。

對於技術掌握與專案檢討

專案有甘有苦,這都是人生啊

Express CRUD 的架構算是滿清楚的,專案的建立也是從『支出花費』的 CRUD 開始建立,難度不是很高,從第二第三個 Model 關聯性的建立,難度變成要怎麼向 MongoDB 取得所需資料。主要是自己對於 asynchronous 非同步的處理不熟悉,導致花了很多時間在『 咦?!資料為什麼沒跑出來 』,後續需要對於非同步的觀念在加強。

當然中間也很多不知道怎麼下手的功能,時常需要看看其他人怎麼做,抓出程式邏輯,再看看以目前已經進行的方向要怎麼調整。或是利用一些關鍵字,例如我在實作的時候,有個功能是篩選出「類別」,需要再使用者篩選後, option 會停留在篩選的結果。這個我卡了好一陣子,也是這次專案中新嘗試的小套件,列出幾個搜尋關鍵字,關鍵字的邏輯是使用哪個套件,在那裡遇到,關鍵字如下:

  • handelbars -> view 使用的套件

  • select -> HTML 標籤

  • option -> select 下的選項

  • selected -> select 被選 的屬性

    結果終於找到,[用 Handlebars 做出保留原始資料的資料][handelbars-helper]
    [handelbars-helper]: https://ithelp.ithome.com.tw/articles/10242260

都成功顯示畫面,不過我又落入沒有設定停損點,導致花了很多時間在問題打轉。

最後是專案需求,有時候自己做一做專案很開心,一個不小心就離主軸目標越來越遠,等到要拉回來的時候,花了很多無謂的時間在 debug ,得不償失。

總結

永遠不會有完美的專案,總是有優化專案的空間
[專案 GitHub 連結][github]
[Heroku 試玩][heroku]
[github]: https://github.com/Kris3131/expense-tracker
[heroku]: https://peaceful-retreat-01550.herokuapp.com/users/login

express-handlebars ERROR

設定 view engine ERROR

express-handlebars@6.0.6 在設定 view engine 出現 error message

app.engine('hbs', exphbs({ defaultLayout: 'main', extname: '.hbs' }))
TypeError: exphbs is not a function

解決辦法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const express = require('express');
const exphbs = require('express-handlebars');

const app = express();
const PORT = 3000;

app.engine('hbs', exphbs.engine({ defaultLayout: 'main', extname: '.hbs' }));
app.set('view engine', 'hbs');

app.get('/', (req, res) => {
res.send(`Hello, World`);
});

app.listen(PORT, () => {
console.log(`Example app listening on http://localhost:${PORT}`);
});

個人專案 - 短網址

Debug 中最大的 Bug 是自己,關於自學的模仿、記憶、理解與創造

這幾天在玩縮短網址專案,縮短網址看似簡單,網路上也有很多 YouTube 教學可以參考,Build a Custom URL Shortener ServiceHow To Build A URL Shortener With Node.js, Express, and MongoDB,所以沒有很直覺地想出要怎麼做專案,我沒有很灰心,畢竟入行沒有很久,大概知道專案邏輯,剩下的就是try and error,但要怎麼 Try 怎麼找到解決 Error 的方法,就是寫 code 有挑戰性的地方。

主要會分成四個『必須』來說明這次怎麼解決專案的問題

Try and Error

必須動手 -> 模仿

網路上有很多資源,就像要開始 URL Shortener 之前,我只有簡單的想幾個步驟:

  1. 讓使用者自行輸入網址
  2. 讀取使用者輸入網址的內容
  3. 製作短網址
  4. 將短網址導回輸入網址的網頁

中間跳過許多執行細節,例如要怎麼檢驗,使用者輸入的內容?輸入的內容有沒有重複?要怎麼製作亂數的短網址?……

這些時候,我會看看別人怎麼做,有沒有哪些功能也可以另外再加上去,或是我沒有注意到的,模仿對我來說可以降低一些挫折的壓力。

模仿似乎變成一種負面的詞彙,『怎麼沒有原創性』,『抄襲仔』的負面印象

但那是因為自己心態不夠健全,模仿不是百分之百一模一樣,而是各取所需,模仿可以讓專案更好的地方。

必須不怕麻煩 -> 記憶

動手不是打架,是正式開始 coding,通常最難,因為需要整理整個專案大概邏輯,畫面要怎麼呈現,還有 set up 專案環境步驟很多。我只是凡人,腦容量不夠,丟三落四變得很正常,像這次專案 set up 需要:

  1. Express -> 建立 localhost
  2. express-handelbars -> 建立 view engine
  3. mongoose 與 MongoDB ->串接資料庫連線
  4. express.Routes -> 將 routes 獨立出來

細微的步驟就只能一再的練習,確認自己知道每一段程式碼是什麼,以我在實作的過程,會畫出 MVC 的架構,把需要串接的工具對應上去,就比較會知道自己在哪裡,做了些什麼事。

必須動手:這是一個無限循環,忘記就再看一次流程,再實作幾次,沒有捷徑。

必須瞭解來龍去脈 -> 理解

原理讓我很想睡,因為原理對我而言很抽象,但因為『原理』是整個電腦在運作的邏輯,也必須瞭解,假如沒有認知到,那 debug 會 de 到想哭。

就像 handelbars 需要透過 controller 帶進需要的資料內容,資料內容沒有對應清楚,畫面永遠跑不出來。透過 mongoose 向 MongoDB 要資料,沒用對的方法拿,當然那些一長串的 error 就會跑滿整個 terminal。

寫程式就是會有很多踩雷的過程,每次踩雷都以為要天崩地裂了,但冷靜下來,原來只是自己觀念不清楚

所以對我而言知道每一段程式碼為什麼存在滿重要的,不然會迷失在錯誤堆中,往不對的方向找答案,只會越來越挫敗。

必須不滿足 -> 創造

是不是可以優化程式碼?是不是可以增加哪些功能?都是可以被額外增加到專案中,有種自己給自己找事做的感覺,這個過程對我而言是一種挑戰專業的機會,是一個很有趣的體驗,完全沈醉在創作。

stay calm

最後,也是滿值得記錄一下關於自學的心態建立,先 debug 自己,再 debug 。每當有 error 都想說,怎麼會我都寫對啊,但不斷地找出問題,不斷的釐清邏輯經過數小時後,就會發現,阿呀原來是觀念不熟悉,或是打錯字等等低級錯誤

冷靜,重新檢視程式碼為什麼會出現錯誤,可能錯誤是出現在哪些地方,是因為語法錯誤嗎?還是有沒有拼錯字,看看別人怎麼做,尋找看看有沒有其他人發生過一樣的問題,一定可以迎刃而解。

debug 只是需要時間跟冷靜地找到問題的方法而已

Node.js Server >>> Express

Node.js?

  • JavaScript 執行環境(run-time environment)
  • 讓 JavaScript 從瀏覽器解放

Node.js server

回傳 HTML >>> Content-Type >>> text/html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// include http module from Node.js
const http = require('http');

// define server related variables
const hostname = 'localhost';
const port = 3000;

const server = http.createServer((req, res) => {
// HTTP status code
res.statusCode = 200;
// HTTP response Headers >>> content-type
res.setHeader('Content-Type', 'text/plain');
// HTTP response Body
res.end('This is my first server created in Node.js');
});

// start and listen the server
server.listen(port, hostname, () => {
console.log(`The server is listening on http://${hostname}:${port}`);
});

Express

  • JavaScript 後端框架

安裝方式

  • npm init / npm init -y
  • npm i express
1
2
3
4
5
6
7
8
9
10
const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => {
res.send('This is my first Express.js app');
});
app.listen(port, () => {
console.log(`Express is running on http://localhost:${port}`);
});

HTML 的 head 有些什麼

HTML 的 head 有什麼

HTML 是網頁的架構,由語意標籤組成,這裡不會特別紀錄標籤,會把重點放在 head裡面有些什麼。
在紀錄 head 之前,會先說明 、 、、 是什麼

HTML 有些什麼?

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body></body>
</html>

文件的種類,告訴瀏覽器文件的種類是 HTML

為什麼需要告訴瀏覽器文件的種類? 與瀏覽器渲染畫面的模式有關。

瀏覽器有三種渲染畫面的模式:

  • quirks mode
  • almost standards mode
  • standards mode

    確保瀏覽器在渲染畫面的時候是在正確模式下進行

  • 標籤內包含整個頁面的內容
  • 又可以被稱為 root element

標籤內的內容不會顯示給使用者看到,包含 HTML 的文件內容

  • title
  • meta
  • CSS / JavaScript
  • script

參考MDN

Rails default database SQLite3 switch to PostgreSQL

Switch SQLite3 to PostgreSQL

Database

database 是資料庫,為什麼需要資料庫?因為 client - server 互動需要資料傳輸, client 傳送資料給 server , server 向 client 顯示資料,或是儲存 client 傳送的資料。所以需要 database 儲存資料。

假如所有資料通通放在一起,沒有一個系統性的整理,會變得很可怕。所以我們可以利用表格的方式整理散亂的資料,table 是資料表格,fields column 是”欄” ,record row 是資料”列”,視覺呈現會是這樣

DBMS

database management system 管理資料庫的系統。MySQL / PostgreSQL

SQL

操作資料庫的語言:SQL (Structured Query language)

實作

Rails 預設使用 SQLite3 作為資料庫,主要是在開發,測試環境上,SQLite3 是一個輕量型的資料庫類型,但到正式產品上線,SQLite3 可能會不夠用。
實作情境大致分成三種,第一種:完美 PostgreSQL 專案建立,第二種:任性手動調整 SQLite3 -> PostgreSQL ,跟最後一種:沒辦法就是要 PostgreSQL

安裝 PostgreSQL

brew install postgresql

使用 homebrew 安裝一鍵搞定

啟動 PostgreSQL

brew services start postgresql
關掉 PostgreSQL
brew services stop postgresql

正常一點,用 PostgreSQL 建立專案

rails new myapp --database=postgresql

意思是:用 rails 直接 new 一個新的專案,database 使用 postgresql。

config/database.yml 檔案中可以看到 database 的設定狀態

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

default: &default
adapter: postgresql
encoding: unicode
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
development:
<<: *default
database: myapp_development
test:
<<: *default
database: myapp_test
production:
<<: \*default
database: myapp_production
username: myapp
password: <%= ENV['MYAPP_DATABASE_PASSWORD'] %>

最後,在用rails db:create的指令讓 rails 和資料庫做連結,

手賤一點,原本是 SQLite3 轉到 PostgreSQL

以這個情境來說,是自己建立專案,獨立開發的狀態下,

一樣, new 一個新的 Rails 專案,
rails new myapp_default_sqlite3

config/database.yml 檔案中可以看到 database 的設定狀態

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

default: &default
adapter: sqlite3
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
timeout: 5000

development:
<<: \*default
database: db/development.sqlite3

test:
<<: \*default
database: db/test.sqlite3

production:
<<: \*default
database: db/production.sqlite3

來吧動手改掉他吧

  • 打開 Gemfile:

    • gem 'sqlite3' 註解掉
    • 加上gem 'pg'
    • bundle
  • 打開 PostgreSQL servicesbrew services start postgresql

- 進入到 PostgreSQL 模式,psql

  • 直接建立資料庫CREATE DATABASE YOUR_DATABASE_NAME

  • 修改 database.yml 檔

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

default: &default
adapter: **postgresql**
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
timeout: 5000

development:
<<: \*default
database: **myapp**

test:
<<: \*default
database: **myapp**

production:
<<: \*default
database: **myapp**

  • rails db:create

成功將 rails 和 PostgreSQL 的資料庫串起來了

第三種情境是沒有選擇,協作專案…

database 的部分,不是自己建的,要怎麼跟自己本機端的 database 串在一起?

這時候需要 PostgreSQL USER_NAME 跟 USER_PASSWORD ,讓這個 database 也可以在本機建立資料。

首先找出自己的 PostgreSQL USER_NAME 跟 USER_PASSWORD ,我的方式是透過 psql 進到資料庫,接者打指令\du,可以列出使用者。

這裡順便把 PostgreSQL 常用語法也列出來。

指令 幹嘛的
\l 顯示所有資料庫
\du 查看所有 USER
\c DatabaseName 切換資料庫
\q 結束
1
2
3
4
5
6
adapter: postgresql
encoding: unicode
database: blog_development
username: YOUR_USERNAME
password: YOUR_PASSWORD
pool: 5

最後一樣,rails db:create,看看有沒有成功的在本地的 PostgreSQL 建立 database

不過要是把 username / password 直接寫在檔案裡,要是進行 Git 版控裡,或是放在 GitHub 中帳號密碼會外洩,這裡有另外一個 gem 套件, dotenv

安裝步驟:

  • 根據 GitHub 上的教學,把 dotenv 放到 Gemfile

    • gem 'dotenv-rails', groups: [:development, :test]
    • 記得bundle
  • 目錄列建立一個.env檔案
    檔案放

    USERNAME: YOUR_USERNAME

    PASSWORD: YOUR_PASSWORD

  • 然後我們就可以直接修改檔案的內容,改成區域變數的方式

1
2
3
4
5
6
adapter: postgresql
encoding: unicode
database: blog_development
username: **<%= ENV['USERNAME'] %>**
password: **<%= ENV['PASSWORD'] %>**
pool: 5

在 Rails 中請記得區域變數一定要加上 <%= %> .erb 檔的寫法

最後就以
brew services stop postgresql
結束這一回合!!!!!!

Routes / MVC

Routes、Model、View、Controller 的概念困擾很久,簡單來說:

MVC 是軟體設計的一種模式(software design pattern),可以參考Wiki

進入 MVC 世界之前,補了一些 Internet 與 Web 的運作邏輯,

Internet 與 Web

什麼是 internet?

  • Internet 是 Web 的基礎,換句話說, Web 是建構在 Internet 之上。

  • Internet 是電腦與電腦之間的連結

    圖片來源:MDN

  • Route 是當電腦間的連結關係複雜時候的一種連結管理

    圖片來源:MDN

  • network 是 Routes 規模變大,連結 Routes 間的連結管理

    圖片來源:MDN

  • ISP(Internet Service Provider) 是 network 間的連結管理

圖片來源:MDN

  • IP(Internet Protocol) 連結到 network 的識別,一連串數字組成 142.250.190.78,但我們連到網頁上不太可能會把一整串數字背出來,所以我們需要 domain namehttps://www.google.com.tw/

什麼是 Web?

Web 是介於客戶(client)與主機(server)之間的關係, client 會向 server 發送請求,server 會回應 client 的需求,網路世界的供需關係。

MDN 關於 Web 的描述很深刻

For now, let’s imagine that the web is a road. On one end of the road is the client, which is like your house. On the other end of the road is the server, which is a shop you want to buy something from.

Web

依照網路世界運作模式來看,可以解釋為什麼在 Ruby on Rails 的建立會依照Routes > Model > View > Controller這樣的順序進行

Routes

路徑是建立 client 與 server 之間橋樑。

Rails 的第一步:設定 Routes。

Routes 的設計是依照REST(Representational State Transfer)的設計風格
REST 翻成專有名詞反而有點難理解,表現層狀態轉移,白話文應該可以說:看網址就知道你要幹嘛,這個留到日後再慢慢補上,免得越陷越深。
回到思考 Routes 的過程,可以理解成把自己想像成使用者,怎樣的網址設計可以讓使用者與設計者一眼就可以知道想看到的內容和需要呈現的內容。
後續再設計 MVC 結構也許可以換一個角度評估:
進入頁面後,

期待看到的內容是什麼?

畫面的操作流程是什麼?

會期待網頁有什麼功能?

是購物型網站?

資訊瀏覽網站?

購物網站?

登入功能應該有哪些?

透過這樣的疑問句來找出需要建立的 Model 需要哪些內容 > View 畫面要怎麼呈現 > Controller 介於 DataBase 與 View 之間的橋樑

Model

Model 是用 Ruby 類別 (class)的方式表示 data,在 Model 透過 Active Record 和 database 拿到需要的資料。
建立 model 需要注意 model_name 的大小寫與單複數問題
這裡可以這樣記:因為 model 是一筆一筆的資料寫進資料庫

bin/rails generate model Article title:string body:text

意思是:用 rails 建立一個 Article 的 model,在這 model 裡面需要的資料結構,title 是 string,body 是 text

ActiveRecord

Active Record 是 MVC 裡面的 M,呈現資料與邏輯
Object Relational Mapping(ORM) system 是連結資料庫的管理架構。

再深入的解釋 Active Record:

  • 呈現 data 跟 model
  • model 之間的關聯性、階層
  • 驗證 Model 的資料格式
  • 用物件導向的方式來呈現資料結構
1
2
class User < ApplicationRecord
end

Database Migration

官方文件對於 Database Migration 的解釋是

Migrations are used to alter the structure of an application’s database. In Rails applications, migrations are written in Ruby so that they can be database-agnostic.

我的理解是:用 Ruby 表示的 database 的資料結構,更好理解。

1
2
3
4
5
6
7
8
9
10
11
12
class CreateResumes < ActiveRecord::Migration[6.1]
def change
create_table :resumes do |t|
t.string :title
t.text :content
t.string :status

t.timestamps
end

end
end

乍看之下,Migration 跟 ActiveRecord 好像有那麼一點像?
沒有他們不一樣!

Migration 是把 database 內的資料格式列出來,所以要調整 column 的項目,可以另外進行一些客製化調整
bin/rails generate migration AddPartNumberToProducts part_number:string

意思是:用 rails 建立一個 migration 檔案,在這檔案裡面需要再加上一個 part_number 的 column 到 products 的 model 中,他的 data type 是 string

1
2
3
4
5
class AddPartNumberToProducts < ActiveRecord::Migration[6.0]
def change
add_column :products, :part_number, :string
end
end

ActiveRecord 是定義資料間的關聯性與驗證資料。

最後在建立 Migration 後還要再將需要的 data type 寫進資料庫,
bin/rails db:migrate
有些人稱為具現化,
我覺得太抽象,
可能更像一種寫進資料庫前的防呆機制,在寫進去之前,要改都是有機會的,寫進去之後就是要在重新 generate 一個 migrate…

View

以 client 的角度而言,當 web 發送一個 request 後,Action Controller 負責與 database 要來的資料,執行 CRUD Action, Action View 會顯示資料的畫面。
View 中還有許多細節,留到接下來的實作紀錄在細細介紹,

Controller

controller 會從 router 那邊接收 request,依照 request 去找 model fetch 或 save data,再透過 view 產生畫面。
Controller 介於 models 和 views 中間,可以讓 model 的 data 可以透過 view 的畫面呈現給 client,也同時讓 client 可以上傳或是儲存 data 到 model 中。