Ruby on Rails 初試啼聲(上)

張凱喬
13 min readOct 27, 2017

--

在上Alpha Camp的課程過程中
其實遭遇滿多阻礙,累積許多一知半解的東西
原因可能在於課程學習流程安排上並不適合我

在這邊應該會匯集一些資源
用我的理解方式,整理成初心者的Rails心得

其中 ihower大神的網站是很重要的資源
他的github跟slideshare也有很多資源。
感恩大神,讚嘆大神。

實體書的話,我覺得這本書內容滿充實
而且可能是因為台灣人寫的,所以閱讀起來很流暢
不會有大部分程式語言書籍有一種翻譯過的生硬感

Ruby on Rails(簡稱Rails)是一個完整的框架
意思是說他包含了前端跟後端

前端比較好意會
因為做出來的東西都是看得見的
包含HTML、CCS以及jQuery等

但是後端相對比較生硬一點
因為必須和Route溝通
或控制資料庫資料等

Rails的優點是在簡易的語法
並且整合了許多方便的指令
可以很迅速建立起互動網頁
讓使用者可以透過網頁讀取或編輯資料

然而有很多方便的指令
對於程式設計師而言並非完全是件好事
因為指令已經包了很多功能,
可能會有多餘的功能都一起完成了(甚至包含了你不想要的)

本文會建立一個簡單的demosite
可以新增、讀取、更新及刪除使用者資料
(上篇只會先建立讀取使用者資料的index)

首先,建立專案,會建立一些基本檔案(說明如下)

rails new demosite
  • Gemfile(設定Rails應用程式會使用哪些Gems套件)
  • README(專案說明,用來告訴其他人你的應用程式是做什麼用的)
  • Rakefile(用來載入可以被命令列執行的一些Rake任務)
  • app/(放Controllers、Models和Views檔案 (重點!!))
  • config/(應用程式設定檔、路由規則、資料庫設定等等)
  • config.ru(用來啟動應用程式的Rack伺服器設定檔)
  • db/(資料庫的結構綱要)
  • doc/(用來放你的文件)
  • lib/(放一些自定的Module和類別檔案)
  • log/(應用程式的Log記錄檔)
  • public/(唯一可以在網路上看到的目錄,這是你的圖檔、JavaScript、CSS和其他靜態檔案擺放的地方)
  • bin/(放rails這個指令和放其他的script指令)
  • test/(單元測試、fixtures及整合測試等程式)
  • tmp/(暫時性的檔案)
  • vendor/(用來放第三方程式碼外掛的目錄)

在終端機輸入以下代碼

rails server

用來在本機端上測試網頁架構
網址是”http://0.0.0.0:3000"

建立好基本的架構之後,開始來處理資料了
這邊先補充一下,Rails上的MVC架構概念

參考高見龍大神的書
所謂MVC就是Model、View、Controller
目的就是讓網頁架構有一個清楚的定位分工

參考下圖
3.Controller接到來自Route解讀過後的指令,開始分派任務
4.7. Model並非資料庫! 只是後端與資料庫溝通的橋樑,用來存入、讀取或編輯資料的設定。
8.9. View則是設定好呈現畫面的結構(包含HTML及CSS等),也可以稱為網頁模板,再把指定的View回傳給Controller

最後,Controller再把資料套進模板,就完成了網頁讀取這個動作囉

接著開始進入MVC

第一部分,先運用Model產生資料

介紹兩種方式建立資料
第一種作法: 先generate model、再migration編輯

rails generate model User

這個是最基本的建立model方式,直接輸入rails generate model+"資料名"
根據CoC原則,一般來說這邊會採用大寫、單數來設定資料名稱

補充解釋CoC(Convention over Configuration)原則,
中文稱為慣例優於設定
意思是,Rails本身會有一些習慣用法
好處是分工時多數工程師都可以理解

generate model之後會產生一些檔案,其中一個比較重要
就是 db/migrate/***_create_users.rb (***是產生時間的標記)

開啟這個.rb檔,接下來針對你需要的欄位進行編輯
也就是在def change這邊要新增的內容
範例是User(使用者)的欄位包含name(名字)、mail(郵件地址)、gender(性別)、age(年齡)

class CreateUsers < ActiveRecord::Migration[5.1]
def change
create_table :users do |t|
t.string :name
t.string :mail
t.string :gender
t.integer :age
t.timestamps
end
end
end

OK之後,就把這個migration這是登記進去資料庫即可
(Rails預設的資料庫是SQLite3)
輸入完下列code就代表你的資料表正式進入資料庫囉

rails db:migrate

第二種方法是: 直接generate帶有欄位的Model

rails generate model User name:string mail:string gender:string age:integer

意思是也不用進migrate再設定欄位名稱了
直接給一個rails db:migrate,就完成了

#補充
工程師懶惰的美德
generate可縮寫為g;欄位為string不用設定、其他都須設定
=> rails g model User name mail gender age:integer

第二部分,產生Controller

在這邊會介紹Controller
Controller有幾個重要功能
1. 設定Action,讓Route對應(也就是讓Route找到對應Controller)
2. 在Action裡設定實例變數,讓View透過Controller讀取Model資料
(3. 也可以在def裡做一些計算、字串操作)

先用指令產生Controller(慣例是複數)

rails generate controller users

如此一般,/app/controllers/users_controller.rb就建立好了
再來,進入controller的設定,會開始跟route、view、model綁一起
會變得有點複雜,需要花一些時間理解

Controller的設定在初學階段,會先理解四種功能
統稱為"CRUD",分別為Create、Read、Update與Destroy

本文會先介紹Read這個功能的設定
等到下一篇文章再一併把CRUD完成

假設我們要在頁面"0.0.0.0:3000/users"
一覽目前所有使用者的資料
我們已經在第一部分完成Model
然後要在第二部分Controller建立功能
第三部分View設定顯示頁面
最後第四部份設定好Route,就可以完成”0.0.0.0:3000/users”

當然這個順序並不是固定的
因為MVC架構下,這些設定都是獨立的
只要設定的變數正確就可以完成彼此串接
也有建議是Route->Controller->Model->View

設定Controller,先進入 /app/controllers/users_controller.rb

class UsersController < ApplicationController
def index
@users = User.all
end
end

def index是為了對應Route的"photos#index"
這個會在Route的部分再說明一次
基本上就是網頁輸入”0.0.0.0:3000/users”
Route會找到 /app/controllers/users_controller.rb的index
以及/app/views/users/index.html.erb

這邊的@users是實體變數(instance)
實體變數可以想像@users是一個獨立的活體
可以直接傳遞到別的功能裡面
Rails中以Controller與View之間的溝通最常用上實體變數
因為需要由Controller設定資料,然後傳遞資料給View

所以User.all是指所有的User資料,指派給@users
接下來這個@users就會被傳進View的功能裡
讓網頁能夠讀取到資料庫的內容

第三部分,產生View

既然都把@users設定好了,就一鼓作氣把View也搞定
首先 /app/views/users這個資料夾在設定Controller時就建好了
但是裡面的檔案要自己建,建立一個index.html.erb

ERb 是指嵌入式的 Ruby 程式碼 (embedded Ruby) ,
讓我們能將 Ruby 程式碼嵌入 HTML 格式的文件

<table>
<thead>
<tr>
<td>姓名</td>
<td>信箱</td>
<td>性別</td>
<td>年齡</td>
</tr>
</thead>
<tbody>
<% @users.each do |user| %>
<tr>
<td><%= user.name %></td>
<td><%= user.mail %></td>
<td><%= user.gender %></td>
<td><%= user.age %></td>
</tr>
<% end %>
</tbody>
</table>

這邊大家都會注意到
網頁竟然不用html、body及head等內容
沒錯,Rails應用了版型Layout的概念
在View裡只需要關注內容,不用在意版型

版型的設定都在views/layout裡
預設使用application.html.erb

也就是說
Controller在顯示畫面時(以這邊index為例)
會把"application.html.erb"與"index.html.erb"兩者結合
最後呈現畫面給使用者

<% @users.each do |user| %>
這邊注意到
<% %>可以使得 Ruby 程式碼可以在 html 格式的頁面中執行,但它所儲存的值不會在網頁瀏覽器上顯示。通常用來包裝沒有必要被顯示的 Ruby 程式碼,例如 each, while, end

<%= %> 可以使得 Ruby 程式碼可以在 html 格式的頁面中執行,但多了一個等號 (=) 就可以在網頁瀏覽器上顯示出內容

第四部份,設定Route

這邊介紹兩種辦法
第一種是自訂、土法煉鋼

打開config/routes.rb,輸入如下

Rails.application.routes.draw do
get "/users", to: "users#index"
end

意思是當使用者輸入 /users 這個網址,它會交由UsersController 上的 index 方法去處理/執行動作

當然也可以傳遞參數
譬如 get "/users/:id", to: "users#show"

就是指把id傳遞到show這個功能
譬如你想要看第101位會員的資料,就可以輸入/users/101

第二種方法則是運用resources
是rails為routes所制定的懶人包
使用一行code直接建立8條路由

Rails.application.routes.draw do
resources :users
end

使用resources :users,建立的路由及對應Action如下
(在終端機上輸入rails routes)

如果你會好奇為什麼網址這麼複雜
譬如說會員101號資料編輯
為何不用"/users_101_edit"或"/usersedit101"就好了呢?

這邊就要介紹一下REST及RESTful概念

REST 是 Representational State Transfer 的縮寫,中文翻譯成「具象狀態傳輸」,它是由 Roy Thomas Fielding 博士在 2000 年時提出的軟體架構。簡單的說,就是把每個網址當做資源(Resource)來看待,對同一個資源做不同的動作(HTTP Verb)會得到不同的結果。符合 REST 概念設計的網址,又稱之 RESTFul Route。

以這邊為例子,users是資源,
所以網址/users/101/edit就是對這項資源去做一個動作
網址上較為直觀,對於開發者提供便利的開發環境

再對應上resources :users的路由設定
就知道Rails基本上也是跟隨REST概念

#補充
1. resource 方法可以是單數的,這個跟複數的 resources 方法的差別在於「單數 resource 方法不會做出含有 :id 的路徑」
使用案例: 譬如說檢視個人會員資料,你只需要看到一個人(就是你的),所以不會有複數的會員資料需要看

2. resources 的應用很多元,譬如說除了預設的八項Action之外,額外自訂。又或者是複數階層的resources(這就跟資料的關聯有關,譬如說每個使用者都有很多篇文章)

詳細參考

如此這般
大概就完成了一個"可以看到使用者資料的頁面"
還不包括"新增、編輯、刪除等功能"

不過概念建立好之後
新增編輯刪除功能會上的滿快的

繼續加油~

--

--

Responses (1)